Got the grid loading using WebWorkers to improve performance and interactivity (note the loading status in the bottom left of the grid). Also add playlists to nav tree on the left and began to style the grid a lot more like itunes.

Sencha touch, YQL and BBC essential mix
So following on from earlier post this week about writing an Ext app which uses YQL to show the BBC radio1 essential mix tracklisting I decided to re-implement the same thing but using the new sencha touch library. Here it is: BBC Essential Mix Trackisting for Android, Ipad and Iphone I’ll post later this week [...]
Playing with Ext.js, YQL and BBC radio1 Essential Mix
I’m a big fan of the radio1 essential mix and list to almost every week. I’m also getting more and more stuck into Ext.js at work. I also saw a great talk by Christian Heilmann of Yahoo at Full Frontal last and he demo’ed YQL. So I thought I’d give it a go and make [...]
Broken Home DJ Set
This is a mix which I did in a club back in Macclesfield in 2001 for a club night called Broken Home. The recording is me preparing in my bedroom a day or two beforehand so excuse the bad scratching and FX. Broken Home Set (demo) 2001 by mattgoldspink
All Vinyl Mix – KISS (2004 REMIX) by PRINCE is now in stock
I finally tracked down a copy of the Soul Of Man Remix of Prince’s Kiss a few weeks back after first hearing it on the Cut & Paste essential mix on Radio 1 back in 2000 (I didn’t realise it was a full 9 years ago!!). It took 5 years to figure out it was [...]
New Summer Mix
It’s not very summery. After seeing 2manydj’s a few weeks back I realised I needed to do some DJing. It’s only 30mins, but it packs in about 20 tunes (including the obligatory Michael Jackson tribute): Download: 11-july-2009.mp3 Tracklist: Hot Chip – Ready For The Floor Cities In Dust (Glimmers Remix). – Junkie XL Hey Boy [...]
A bit more progress on the itunes themed UI
New Subsonic Web UI!
So a quick post about a new Subsonic web UI I’ve been working on based on Itunes. Here’s a sneak peak at it:




Can’t boot into Windows XP after installing Ubuntu 10.4 (Lucid Lynx)
I upgraded to Lucid a few months ago but have not been able to use my windows partition since. Everytime I select it from Grub2 it just goes to a grub style prompt and I can’t do much. I finally found a solution here: http://sourceforge.net/apps/mediawiki/bootinfoscript/index.php?title=Boot_Problems:Boot_Sector which worked beautifully first time and I’m now back into XP!
JSON, JSR-303, Spring MVC and Ext.js
So I thought I’d post this in case others hit it. If you want to Spring MVC and POST JSON from an Ext JsonWriter to the server and have it populate your bean model and also get validated by JSR-303 validator then you’ll need to do a little work because it doesn’t work out of the box.
In the end I had to do some ugly classpath overriding to get it to work in the way I expected by writing my own modified version of Spring’s HandlerMethodInvoker. If you hit similar issues I suggest following this JIRA: http://jira.springframework.org/browse/SPR-7114 and feel free to use the attached code on the JIRA. It’s been working great for me now.
Re-visiting Spring, Ivy and Maven – copy and paste configs
So its been a while since I did any Java development at home and having done enough at work I figured I would get a basic ivy setup with all the regular dependencies that I use for 90% of the projects I do at the firm and am likely to do at home so I can just copy and paste in the future. So feel free to… copy and paste!
I’m using Eclipse 3.5 with the IvyDE plugin. With those installed I created a new Java Project and then set about creating my ivy.xml. My projects pretty much all have the same basic dependencies
- Spring (3.0.3.RELEASE since that’s the latest)
- Hibernate (3.5.3.Final)
- Hibernate-search (Makes indexing my model nice and easy)
- Jodatime (Awesome for date manipulation)
- Jodatime-hibernate
- H2 database (I always start of with a mock in-memory at start of dev and then use some JPA magic to dump out a schema to DB2 or Sybase, or whatever else DB is in use)
- SLF4J (My logging api of choice)
- Jackson (For any restful services I might write)
Here’s my ivy.xml
< ?xml version="1.0" encoding="UTF-8"?> < ?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?> <ivy -module xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd" version="1.3"> <info organisation="mattgoldspink" module="gtdtd" revision="1.0.0" status="integration"> <license name="Apache 2.0" url="http://www.apache.org/licenses/LICENSE-2.0"/> </info> <configurations> <conf name="compile" visibility="public" description="Maven compile dependencies"/> <conf name="runtime" visibility="public" extends="compile" description="Runtime dependencies"/> <conf name="test" visibility="private" description="Test dependencies"/> </configurations> <dependencies> <dependency org="org.springframework" name="org.springframework.spring-library" rev="3.0.3.RELEASE" conf="runtime->runtime" /> </dependency><dependency org="org.hibernate" name="hibernate-core" rev="3.5.3-Final" conf="runtime->*" /> </dependency><dependency org="com.h2database" name="h2" rev="1.2.137" conf="runtime->*" /> </dependency><dependency org="org.hibernate" name="hibernate-validator" rev="4.0.2.GA" conf="runtime->*" > <exclude org="org.slf4j" name="slf4j-log4j12" /> </dependency> <dependency org="org.hibernate" name="hibernate-entitymanager" rev="3.5.3-Final" conf="runtime->*" /> </dependency><dependency org="org.hibernate" name="hibernate-search" rev="3.2.0.Final" conf="runtime->*"> <exclude org="javax.jms" name="jms" /> </dependency> <dependency org="joda-time" name="joda-time" rev="1.6" conf="runtime->*" /> </dependency><dependency org="org.hibernate.javax.persistence" name="hibernate-jpa-2.0-api" rev="1.0.0.Final" conf="runtime->*" /> </dependency><dependency org="joda-time" name="joda-time-hibernate" rev="1.2" conf="runtime->*"> <exclude org="org.hibernate" name="hibernate" /> </dependency> <dependency org="org.slf4j" name="slf4j-api" rev="1.5.6" conf="runtime" force="true"/> <dependency org="org.slf4j" name="slf4j-log4j12" rev="1.5.6" conf="runtime" force="true"/> <dependency org="org.codehaus.jackson" name="jackson-core-lgpl" rev="1.5.3" conf="runtime" /> <dependency org="org.codehaus.jackson" name="jackson-mapper-lgpl" rev="1.5.3" conf="runtime->*" /> </dependency></dependencies> </ivy>
I’m going to get my spring dependencies from Springsource’s ivy/maven repository, but everything else will come from a mix of JBoss and Maven2 repo’s. Here’s the ivy-settings.xml
< ?xml version="1.0" encoding="ISO-8859-1"?> <ivysettings> <caches artifactPattern="[organisation]/[module]/[revision]/[artifact].[ext]" /> <settings defaultResolver="ibiblio.jboss.java-net.springsource" checkUpToDate="true" /> <resolvers> <chain name="ibiblio.jboss.java-net.springsource"> <ibiblio name="ibiblio" m2compatible="true" /> <ibiblio name="jboss" m2compatible="true" root="https://repository.jboss.org/nexus/content/groups/public-jboss" /> <ibiblio name="java.net" m2compatible="true" root="https://repository.jboss.org/nexus/content/repositories/java.net-m2/" /> <ibiblio name="java.net" m2compatible="true" root="http://repository.codehaus.org/" /> <url name="com.springsource.repository.libraries.release"> <ivy pattern="http://repository.springsource.com/ivy/libraries/release/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /> <artifact pattern="http://repository.springsource.com/ivy/libraries/release/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /> </url> <url name="com.springsource.repository.libraries.external"> <ivy pattern="http://repository.springsource.com/ivy/libraries/external/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /> <artifact pattern="http://repository.springsource.com/ivy/libraries/external/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /> </url> <url name="com.springsource.repository.bundles.release"> <ivy pattern="http://repository.springsource.com/ivy/bundles/release/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /> <artifact pattern="http://repository.springsource.com/ivy/bundles/release/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /> </url> <url name="com.springsource.repository.bundles.external"> <ivy pattern="http://repository.springsource.com/ivy/bundles/external/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /> <artifact pattern="http://repository.springsource.com/ivy/bundles/external/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /> </url> </chain> </resolvers> </ivysettings>
After plugging the above into Eclipse and setting up my IvyDE classpath container to use the new ivy-settings.xml file there was one more thing to do which was to tell IvyDE what type the source jars were. Go to “Window” -> “Preferences”, find “Ivy” -> “Classpath” in the tree and on that page under the option for “Source types” enter “source,src,srcs”. Save and you should get source code attachment to the jars too. Note that you can tell your Eclipse project to use the ivy-settings within it by going right clicking on your Ivy classpath container and under “Ivy Settings Path” enter project:///ivy-settings.xml
Sencha touch, YQL and BBC essential mix
So following on from earlier post this week about writing an Ext app which uses YQL to show the BBC radio1 essential mix tracklisting I decided to re-implement the same thing but using the new sencha touch library.
Here it is: BBC Essential Mix Trackisting for Android, Ipad and Iphone
I’ll post later this week details about how it works. For now take a look at the source code and enjoy.
Playing with Ext.js, YQL and BBC radio1 Essential Mix
I’m a big fan of the radio1 essential mix and list to almost every week. I’m also getting more and more stuck into Ext.js at work. I also saw a great talk by Christian Heilmann of Yahoo at Full Frontal last and he demo’ed YQL. So I thought I’d give it a go and make a quick Ext app which uses YQL and pulls in the data of the tracklists for the Radio 1 Essential Mixes…
And here it is: http://www.mattgoldspink.co.uk/bbcradiolastfm.html
To give a brief summary of how I did it
- Getting the tracklisting from the BBC
This basically involved me picking out a rough top level element from an essential mix page of tracks (firebug is lord). This resulted in the below YQL query:select * from html where url="http"+"://ww"+"w.bbc.co.uk/programmes/b00sdb2z" and xpath='//div[@class="title" or @class="title with-image"]'
- Now getting this into a simple Ext.js ListView
It was obvious to me I needed a Ext.data.ScriptTagProxy to achieve this in order to get the JSON-P cross domain call. Unfortunately the hard bit is getting the JSON from the YQL call into the right format for my JsonStore in Ext. Thankfully Ext has all the necessary hooks to do this it looks something like:var dataStore = new Ext.data.JsonStore( { proxy : new Ext.data.ScriptTagProxy( { url : 'http'+'://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22http%3A%2F%2Fw'+'ww.bbc.co.uk%2Fprogrammes%2Fb00sdb2z%22%20and%0A%20%20%20%20%20%20xpath%3D\'%2F%2Fdiv%5B%40class%3D%22title%22%20or%20%40class%3D%22title%20with-image%22%5D\'&format=json', callbackParam: 'callback', restful: true } ), root: 'query.results.div', fields: [{ name : 'artist', convert : Ext.ux.mattgoldspink.bbcessentialmix.getArtistFromJson },{ name : 'track', convert : Ext.ux.mattgoldspink.bbcessentialmix.getTitleFromJson }], allowBlank: false } );Where the convert functions were:
function js_traverse(o, keyName) { var type = typeof o; if (o.class && o.class === keyName) { return o.content; } if (type == "object") { for (var key in o) { var output = js_traverse(o[key], keyName); if (output) { return output; } } } else { return undefined; } }; Ext.ux.mattgoldspink.bbcessentialmix.getArtistFromJson = function(v, rec) { var artist = js_traverse(rec, 'artist'); if (artist) { return artist; } else { return 'Unknown'; } }; Ext.ux.mattgoldspink.bbcessentialmix.getTitleFromJson = function(v, rec) { var artist = js_traverse(rec, 'track'); if (artist) { return artist; } else { return 'Unknown'; } };The interesting part here is that the BBC very helpfully markup all their tags so all I had to do was traverse the messy JSON tree until I found a class which marked either the title or artist and then return it (or ‘Unknown’ if it was there).
Next we plug this into our Ext.ListView:var listView = new Ext.list.ListView({ id: 'listview', store: dataStore, multiSelect: true, emptyText: 'No tracks found', columnSort: false, loadingText: 'Updating tracklist', tpl: new Ext.XTemplate( '<tpl for="rows">', '</tpl><tpl exec="values.row = xindex;">', '<dl>', '<tpl for="parent.columns">', '<dt style="width:{[values.width*100]}%;text-align:{align};">', '<em unselectable="on"<tpl if="cls">', ' class="{cls}</em></dt></tpl>">', '{[values.tpl.apply(parent)]}', '<div class="x-clear"></div>', '</dl>', '' ), columns: [ { header: 'Track #', width: 0.04, align: 'left', dataIndex: 'row' },{ header: 'Artist', width: 0.48, align: 'left', dataIndex: 'artist' },{ header: 'Track', width: 0.48, align: 'left', dataIndex: 'track' }] });This code is a bit more complicated than I expected because by default Ext.ListView does not with the Ext.grid.RowNumberer, so after a bit of google-fu I discovered a post showing how to achieve this using the tpl property.
- Getting all the possible Essential Mixes
I decided I’d add a TreePanel so you can pick other essential mixes and view their tracks too. To do this I needed to jump back to firebug and YQL to get the available tracklists. In short my YQL query ended up beingselect * from html where url="http://www.bbc.co.uk/programmes/b006wkfp/episodes/2009" and xpath='//a[@class="url"]'
- Getting the TreePanel to pull in the data from YQL
Again this is something I thought was going to be tough, but after looking at a few blog posts and examples I realised it was possible. My final TreeLoader implementation looks like:Ext.ux.mattgoldspink.bbcessentialmix.TreeLoader = function(){ Ext.ux.mattgoldspink.bbcessentialmix.TreeLoader.superclass.constructor.call(this); this.proxy = new Ext.data.ScriptTagProxy({ url : this.dataUrl, callbackParam: 'callback', restful: true }); }; Ext.extend(Ext.ux.mattgoldspink.bbcessentialmix.TreeLoader, Ext.tree.TreeLoader, { dataUrl: 'http:'+'//query.yahooapis.com/v1/public/yql?' +'q=select%20*%20from%20html%20where%20url%3D' +'%22http%3A%2F%2Fwww.bbc.co.uk%2Fprogrammes' +'%2Fb006wkfp%2Fepisodes%2F2010%22%20and%0A' +'%20%20%20%20%20%20xpath%3D\'%2F%2Fa%5B' +'%40class%3D%22url%22%5D\'&format=json', requestData : function(node, cb){ this.proxy.setApi( Ext.data.Api.actions.read, 'http'+'://query.yahooapis.com/v1/public/yql?' +'q=select%20*%20from%20html%20where%20url' +'%3D%22http%3A%2F%2Fww' +'w.bbc.co.uk%2Fprogrammes%2F' +'b006wkfp%2Fepisodes%2F' + node.attributes.nodeid + '%22%20and%0A%20%20%20%20%20' +'%20xpath%3D\'%2F%2Fa%5B%40class' +'%3D%22url%22%5D\'&format=json'); this.proxy.request('read', null, {}, { readRecords : function(o){ return o.query.results.a; } }, this.addNodes, this, {node:node, cb:cb}); }, addNodes : function(o, arg){ var node = arg.node; for(var i = 0, len = o.length; i < len; i++){ var foo = {}; foo.text = o[i].span.content, foo.url = o[i].href.replace("/programmes/", ''); foo.leaf = true; var n = this.createNode(foo); if(n){ node.appendChild(n); } } arg.cb(this, node); } });The key bits here are that before I request data for a node I change the YQL query to pick up the data for the year node that was clicked. Then once the results come back I pull out the results node from the JSON and in my addNodes function I set up leaf node.
- The onclick callback to reload the ListView with new tracklists
When someone clicks one of these new tracklist nodes in the TreePanel we want to update the ListView. This was done by adding a listener to the TreePanel:listeners: { click: function(n) { Ext.getCmp('listview').getStore().proxy.setApi( Ext.data.Api.actions.read, 'http://query.yahooapis.com/v1/public/yql?' +'q=select%20*%20from%20html%20where' +'%20url%3D%22http%3A%2F%2Fww' +'w.bbc.co.uk%2Fprogrammes%2F' + n.attributes.url +'%22%20and%0A%20%20%20%20%20%20' +'xpath%3D\'%2F%2Fdiv%5B%40class%3D' +'%22title%22%20or%20%40class%3D' +'%22title%20with-image%22%5D\'&format=json'); Ext.getCmp('listview').getStore().load(); } }We simply change the read action url in the ListView store’s proxy, then we reload the store! As simple as that.
To wrap it up I put it all in an Ext.Viewport. Feel free to view the source of the page and enjoy!
http://www.mattgoldspink.co.uk/bbcradiolastfm.html
Tomcat6 issues upgrading to Ubuntu 10.4 Lucid Lynx
I thought I’d post this in case anyone else hits similar issues upgrading to Ubuntu 10.4. So after following all the steps I decided to keep my existing tomcat6 script under /etc/init.d/tomcat6 because I’d customised it for launching Subsonic Music Server. However after restarting my machine after upgrading I noticed subsonic was not running. So I dug a bit deeper and found that I was missing the jsvc package. Running:
sudo apt-get install jsvc
got me sorted and Subsonic is back alive!






