ExtJS 5 and Gradle – Playing Together

Augmenting ExtJS with Gradle

ExtJS is pretty nice, overall, and it comes with a powerful build tool – Sencha Cmd.

Running builds with it can be tedious, because it doesn’t have any up-to-date checks – it constantly rebuilds stuff it doesn’t need. Oh, the time wasting!

As it turns out, Sencha Cmd is an Ant-based build tool. Which means we can create Gradle builds that augment it – given us support for such things as up-to-date checks.

Like this:

ant.importBuild 'build.xml'
def packages_dir = file('../packages')
clean {
doLast { delete 'bootstrap.js', 'bootstrap.css', 'bootstrap.json' }
}
refresh {
inputs.dir 'app'
inputs.file 'app.json'
packages_dir.listFiles().each() { package_dir -> inputs.dir new File(package_dir, 'src') }
outputs.file file('bootstrap.js')
outputs.file file('bootstrap.json')
}
js {
inputs.dir 'app'
packages_dir.listFiles().each() { package_dir -> inputs.dir new File(package_dir, 'src') }
outputs.file file("../build/${this.property('build.environment')}/${projectName}/app.js")
}
resources {
inputs.dir 'resources'
packages_dir.listFiles().each() { package_dir -> inputs.dir new File(package_dir, 'resources') }
outputs.file file("../build/${this.property('build.environment')}/${projectName}/resources")
}
sass {
inputs.dir 'sass'
packages_dir.listFiles().each() { package_dir -> inputs.dir new File(package_dir, 'sass') }
outputs.file file("../build/${this.property('build.environment')}/${projectName}/resources/${projectName}-all.css")
outputs.file file('bootstrap.css')
}
page {
// what are the inputs to page, I wonder?
// the outputs are the microloader.js and the index.html...
}
view raw build.gradle hosted with ❤ by GitHub
# the default Build Environment. Production is the default for Sencha Cmd.
# Use -Dbuild.environment on the command line to change, otherwise it doesn't get passed to the ant build properly
build.environment=production
# The project name. Should match what is in the app.json file
projectName=MyApp

Share and Enjoy!

Object equality is context sensitive

Equality is context sensitive. It’s very rarely as cut-and-dried as people think it is.

As a simple example, consider two $5 notes. I think everyone can agree that these notes have the same value – they are both worth $5. But are they equal?

Continue reading “Object equality is context sensitive”

Immutable objects the lazy way

Building properly immutable objects in Java can be annoying, especially if they’ve got a bunch of properties – too many to put into a readable constructor.1

You can implement the Builder pattern, but a lot of the time that just feels like overkill. But you don’t want to put in a bunch of setter methods, because that’s just asking for trouble. So what do you do?

Continue reading “Immutable objects the lazy way”

Java, Equality, Mutability

TL;DR version: Don’t implement equals() on mutable objects.

This is a post I’ve been tossing around for a couple of years, ever since a lunchtime debate with a colleague. It’s a simple statement: You shouldn’t implement the equals() method if your object isn’t immutable.1

Continue reading “Java, Equality, Mutability”

Example Hadoop Job that reads a cache file loaded from S3

I had all sorts of problems getting my head around how cache files work with Hadoop. Finally, I stumbled across the answer – when you add a cache file (see HadoopMain#48), it’s available to read as a local file inside the mapper (MyMapper#36).

When running in Elastic MapReduce, the file URI can be an S3 file, using either s3://bucket/path or s3n://bucket/path – this may or may not work in other Hadoop implementations, but the general approach would work fine.

See the gist at https://gist.github.com/twasink/8813628

How-To: Grails, GORM and SimpleDB

I went to build a new Grails-based app today, and I wanted to use SimpleDB as a backend (the app is an internal-use administration app, to configure a suite of AWS-deployed apps). So I went looking on how to use GORM with SimpleDB. This turned out to be a non-trivial task, so I thought I’d share the process with everyone.

Continue reading “How-To: Grails, GORM and SimpleDB”

Building Dependent Maven Projects in Bamboo

For the last year or so, I’ve been using Atlassian’s Bamboo (in the OnDemand variant) for our team’s build server. And, mostly, it’s an awesome tool. Some parts, however, are a little rough around the edges. Building dependent projects is one of them.

Continue reading “Building Dependent Maven Projects in Bamboo”

Lessons learnt from a bug

This is a rant about a bug report I raised with ExtJS a few weeks ago. That said, I’m using the bug more as a teachable moment than anything else; I’m certainly not trying to bag ExtJS (which I quite like, despite some of its quirks). But this bug does highlight a number of “things done wrong”, which I want to learn from so that I don’t commit the same errors.

(No knowledge of ExtJS is required, and whilst I will describe the details of the bug in depth, the technical issues involved aren’t meant to be the takeaway points)

Continue reading “Lessons learnt from a bug”

Giving the ‘hasOne’ association some love

One of the really nice features of ExtJS, to my mind anyway, is the rich model architecture, and how models can be associated with each other. However, the quality can be a bit erratic – certainly, it appears that the HasOne association (which allows a one-to-one relationship) could use some loving, as it isn’t as well developed as the more commonly-used HasMany

Continue reading “Giving the ‘hasOne’ association some love”

Reading Associative Arrays with ExtJS Models

Wow, it’s been a while since I posted something…

I’ve been working a lot with ExtJs recently, as the basis for a web application which talks to a lot of JSON-based web services. And I got to say that I am enjoying it – it’s a nice, powerful framework that makes working with JavaScript quite bearable.

ExtJs includes a sub-framework for turning JSON (or XML) data into ‘models’, including nested data. It does this by providing ‘reader‘ classes that understand JSON (or XML). However, it only understands nested arrays. Sometimes what you have is a nested object – e.g. when you serialize a HashMap from Java into JSON. Fortunately, it’s possible to extend ExtJS and provide a new Reader – one that understands nested objects (aka ‘maps’, or ‘hashes’, or ‘associative arrays’).


/**
* A variant of the JSON reader. Instead of reading arrays, where each record in the array field
* has an 'id' property, it reads objects – aka associative arrays. The key of the entry will be the
* array.
*
* So where the JSON reader would like data like this:
* [ { id: '1', property: 'foo' }, { id: '2', property: 'bar' } ]
*
* the associative reader likes data like this:
* { '1': { property: 'foo' }, '2': { property: 'bar' } }
*/
Ext.define('Twasink.data.AssociativeReader', {
extend: 'Ext.data.reader.Json',
alias: 'reader.associative',
readRecords: function(data) {
// convert the associative array into a normal array.
var idProperty = 'id'; // should be a config value?
var arrayData = []
Ext.Object.each(data, function(key, value) {
var arrayEntry = {};
Ext.Object.merge(arrayEntry, value);
arrayEntry[idProperty] = key;
arrayData.push(arrayEntry);
});
return this.callParent( [ arrayData ]);
}
})


Ext.define('Twasink.model.Bar', {
extend: 'Ext.data.Model',
idProperty: 'id',
fields: [ 'baz', 'bux']
})

view raw

Bar.js

hosted with ❤ by GitHub


[
{ "id": "foo_1", "baz": "baz_1", "bux": "bux_1", "bar": {
"bar_1": { "baz": "bar_baz_1", "bux": "bar_bux_1" },
"bar_2": { "baz": "bar_baz_2", "bux": "bar_bux_2" }
}
},
{ "id": "foo_2", "baz": "baz_2", "bux": "bux_2", "bar": {
"bar_1": { "baz": "bar_baz_3", "bux": "bar_bux_3" },
"bar_2": { "baz": "bar_baz_4", "bux": "bar_bux_4" }
}
}
]


Ext.define('Twasink.model.Foo', {
extend: 'Ext.data.Model',
requires: [ 'Twasink.data.AssociativeReader', 'Twasink.model.Bar' ],
idProperty: 'id',
fields: [ 'baz', 'bux'],
hasMany: [ { model: 'Twasink.model.Bar', name: 'bars', associationKey: 'bar', reader: 'associative' }]
})

view raw

Foo.js

hosted with ❤ by GitHub

If you’re using ExtJS, I hope you find this useful.