Sunday, September 25, 2011

Simplifying External TagLibs with Proxies

I am the proud author of the jQuery-UI-Widget Grails Plugin.   I built this plugin to enable Grails developers the ability to create jQuery-UI widgets without dealing with JavaScript directly.   This allows Grails developers to use the resources they are familiar with while still building cool, rich User Interface components.

This post isnt about my plugin.  Instead, its about how engineers can better utilize plugins like mine.  

One of the challenges I've faced when leading a team of developers is this... How can I enforce all components of a certain type are built the same way, especially when I dont control the construction of the component itself.  A non-abstract example of this issue is this... Developers on my team are all creating jQuery-UI AutoCompletes via the TagLib.  How do I ensure all the AutoComplete configuration properties are the same?

The answer is simple.  You require all instantiations of the component to go through your own code.  This is called the Proxy Pattern.  In practice, you create a wrapper that your developers call.  This wrapper is responsible for setting the standard configuration properties for the component and creating the component itself.  The ability to override or further customize the component can be easily implemented as well.

Lets look at an example using a custom Grails Tag and my jQuery-UI-Widget plugin.  I'm going to encapsulate the jQuery-UI AutoComplete in my own tag.

def myautocomplete = { attrs, body ->

 // grab the id
 def id = attrs.remove("id")

 // create a config to pass to taglib
 def acConfig = [:]
 // pass the id along to the config
 acConfig.id = id
 // throughput the widget config or create a new one
 acConfig.config = attrs.remove("config") ?: [:]
 // enforce the delay property 
 acConfig.config.delay = 200 
 // set the minLength property if not overridden by instance config
 acConfig.config.minLength = acConfig.minLength ?: 1 

 //call the jquery-ui taglib
 out << jqueryui.jquiAutoComplete(acConfig, body)

}

This Tag is a Proxy to the jQuery-UI TagLib's jquiAutoComplete tag. The config is passed along to the target tag after any defaults are set. Doing this allows me to enforce a standard for our application's jQuery-UI Widgets.




Thats is. The idea is pretty simple overall, but flexible enough to allow my team to build the Widgets we need for our application. I've applied this approach to jQuery-UI Widgets, YUI2 Widgets and DataTables.

Tuesday, September 6, 2011

Extending jQuery-UI Widgets

I recently needed to extend the jQuery-UI AutoComplete Widget for a few custom features. The act of extending the Widget was relatively easy, but its not the entire story. Simply extending the jQuery-UI Widget will cause you to lose native functionality. Here is what I'm talking about...

Say I want to extend the jQuery-UI Widget...
$.widget("ui.myAC", $.ui.autocomplete, {
    myMethod : function(){
    },
    myOverride : function(){
        self.myOverride()
    }
});

Doing this allows me to instantiate my custom widget...
$("#myInput").myAC({});

However... the following wont work.
$("#myInput").myAC("search", "%");

Calling the widgets public methods will fail. A little debugging shows me that jQuery-UI doesnt think that method exists. Hmm... I extended a jQuery-UI Widget, but I lost the native methods. Boo!

Since jQuery-UI Widget extension has changed recently, Google didnt provide me with an obvious answer. However, I kept stumbling upon this thing called a Bridge.

Lets try it...
$.widget.bridge("myAC", $.ui.myAC);

Woot! I now have access to the native methods. Now my custom widget is fully functional.

I could attempt to explain all the different things $.widget.bridge does for us, but I'd do a poor job. Here are some folks that have already explained it.
Eric Hynds
Alex Sexton

Monday, August 1, 2011

Grails Plugins and Default Configs

I've been working on Grails plugins for jQueryUI and YUI2.  One of my ideas was to use a default config within my plugin, which the plugin consumer could override and modify the config values for their usage.

Unfortunately, Grails doesn't provide this feature by default.  You can use the plugin's Config.groovy for settings when you test, but it doesnt work when the plugin is being ran from an app.  Unless...  you do the following.

Lets say your creating the next awesome plugin.  We'll call it Foo.

1.  Create a groovy config file that is unique to your plugin.  Mine is FooConfig.groovy. Inside, put your config values.
fooConfig {
  fooVar = "Hello World"
}

2.  Load your new config via the FooGrailsPlugin.groovy file.  This code is a modified version of the code found in Spring-Security-Core plugin.  Thanks Burt.
def doWithSpring = {
  mergeConfig(application)
}
private void mergeConfig(GrailsApplication app) {
  ConfigObject currentConfig = app.config.grails.fooConfig
  ConfigSlurper slurper = new ConfigSlurper(Environment.getCurrent().getName());
  ConfigObject secondaryConfig = slurper.parse(app.classLoader.loadClass("FooConfig"))

  ConfigObject config = new ConfigObject();
  config.putAll(secondaryConfig.fooConfig.merge(currentConfig))

  app.config.grails.fooConfig = config;
}

3.  Finally, we need to make our plugin config reload when a config is changed elsewhere in the application.
def onConfigChange = { event ->
  this.mergeConfig(application)
}

Thats it. Thats all I had to do. Now I can use default configs within my plugin and allow my plugin consumers to customize. Fun Stuff.

Here is an example of customization...
grails.fooConfig.fooVar = "I've been updated!"

Full Disclosure : I havent tested this in a deployed WAR yet.
Works from run-war.

Referenced Links
Post 1
Post 2

Monday, June 13, 2011

Debugging Grails Controllers & Closures in IntelliJ

We're using IntelliJ at work for our Grails development.  IntelliJ is a solid IDE with great Grails support.  I should have no complaints... but this one issue has been nagging at me.  When using IntelliJ to debug Grails, I couldn't use the Watch Window to interrogate a Controller Action's arguments.

Setting a watch variable to params or request in the following action closure yields...
Cannot find local variable 'params'
def myAction = {
}

Of course, if we set the params argument to a reference, then we can interrogate it. So we know the object is there... so what gives?
def myAction = {
  def myParams = params
  def myRequest = request
}

The answer is simple and opaque at the same time. Closures aren't methods. I'm guilty of forgetting this and Grails is great about hiding this fact from us.  However, IntelliJ isn't that smart.  When debugging in IntelliJ, we have ask the Closure the right question.
this.getProperty("params")

Ah Ha! There is my params argument in IntelliJ.  Now I can stop writing println everywhere...

More info on Closures
Formal Definition
Informal Guide

Thursday, May 19, 2011

Grails, Envers and Blob

We've added Hibernate Envers to our Grails project.  Thus far, Envers has handled all our object versioning requirements...  Until we tried to use a Blob.

@Audited
class Data {
    Blob data
}

org.hibernate.MappingException : Type not supported for auditing: org.hibernate.type.BlobType, on entity Data, property 'data'.

What is the solution?  Envers does not throw an exception for a Byte Array, so replace Blob with it.  However, MySQL will map the Byte Array to a TinyBlob, which may not work for you.  You can modify this by updating the GORM DSL on the domain.

@Audited
class Data {
    byte[] data
    static mapping = {
        data sqlType: 'blob'
    }
}

This resolved the problem for us.