2008-02-29

Grails app.version & plugin utopia

I was catching up on my reading recently when I came across
this post. The technique Darryl is using to show application version numbers to his users is:
v${grailsApplication.metadata.'app.version'}

Which makes perfect sense to me. In fact, I don't understand why it's not in the Grails defaults to show the version number. If you add that line to your grails-app/views/layouts/main.gsp or add the version number to the default title every page would get a version stamp. I can't see how it would be obtrusive either since you could remove it or change where it was placed yourself later.

The other news that I think is interesting on aboutGroovy.com is the Selenium plugin for Grails. This is indicative of what could be a major selling point for Grails. It can easily make use of all kinds of existing Java tools as plugins. And do it today.

But, it's not only that you get to use these tools, Grails provides an interesting distribution mechanism for the tools as well.

You install grails plugins from the command line and you list out available plugins the same way for example:

$ grails list-plugins

Welcome to Grails 1.0 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: /usr/local/grails

Base Directory: /home/shawn/workspace/myproject
Environment set to development
Running script /usr/local/grails/scripts/ListPlugins.groovy
[mkdir] Created dir: /home/shawn/.grails/1.0/plugins
Plugins list cache does not exist or is broken, recreating ...
Plugins list cache has expired. Updating, please wait... ...

Plug-ins available in the Grails repository are listed below:
-------------------------------------------------------------

acegi -- No description available
aop -- No description available
autorest -- No description available
axis2 <0.1> -- Add Web Service support for Grails services using Apaxhe Axis2.
cache -- No description available
cas-client <0.2> -- This plugin provides client integration for JA-SIG CAS
code-coverage <0.7> -- Generates Code Coverage reports
converters <0.3> -- Provides JSON and XML Conversion for common Objects (Domain Classes, Lists, Maps, POJO)
dbmapper <0.1.7> -- Database relation to domain object generator
dbmigrate <0.1.5> -- Database migration tasks
djangotemplates -- No description available
dojo <0.4.3> -- Provides integration with the Dojo toolkit http://dojotoolkit.org, an Ajax framework.
dwr <0.1> -- This plugin adds DWR capabilies to the services in a Grails application.
eastwood-chart <0.1> -- This plugin wraps JFreeChart's Eastwood servlet for Grails app
echo2 <0.1> -- Echo2 capabilities to Grails applications
ext-ui -- No description available
fck-editor <0.3> -- FCKeditor
feeds <1.2> -- Render RSS/Atom feeds with a simple builder
flex <0.1> -- Provides integration between Grails and Flex
google-chart <0.4.3> -- This plugin adds Google Chart API features to Grails applications.
gwt <0.2.4> -- The Google Web Toolkit for Grails.
i18n-templates <1.0.1> -- I18n Templates
ivy <0.1> -- The Ivy Dependency Manager for Grails.
jasper <0.5> --
jcaptcha <0.2> -- Grails JCaptcha Plugin
jcr -- No description available
jms <0.3> -- This plugin adds MDB functionality to services.
jsecurity <0.1.1> -- Security support via the JSecurity framework.
jsf -- No description available
laszlo <0.6> -- OpenLaszlo plugin for Grails
ldap <0.1> -- Adds easy to use LDAP connectivity
liquibase <1.5.2.0> -- LiquiBase Database Refactoring for Grails
modalbox <0.1> -- This plugin adds the ModalBox to your Grails applications.
mondrian <0.1> -- This plugin installs Pentaho Mondrian into your Grails application.
ofchart <0.5> --
portlets -- No description available
quartz <0.2> -- This plugin adds Quartz job scheduling features to Grails application.
radeox <0.1> -- A plugin for the Radeox Wiki-render engine to allow easy markup and cross-linking.
remoting <0.3> -- Adds easy-to-use server-side and client-side RPC support.
richui <0.2> -- Provides a set of AJAX components
scaffold-tags <0.7> -- Adds tags to support fully-customizable & dynamic scaffolding
searchable <0.4-SNAPSHOT> -- Adds rich search functionality to Grails domain models.
staticresources -- No description available
webtest <0.3> -- A plug-in that provides functional testing for Grails using Canoo Web Test
wicket <0.3> -- Provides integration between Grails and the Wicket framework
xfire <0.7.4> -- Add Web Service support for Grails services using XFire.
xmlrpc <0.1> -- This plugin adds XML RPC functionality to GRAILS
yui <2.5.0> -- Yahoo! User Interface Library (YUI)
yui-widgets <0.1> -- Yahoo! User Interface Library (YUI) Widgets

To find more info about plugin type 'grails plugin-info [NAME]'

To install type 'grails install-plugin [NAME] [VERSION]'

For further info visit http://grails.org/Plugins


This is interesting not because this is new for Java programs, but, because the Grails plugin repository is now a Java Software distribution system. I think we'll see this eventually morph into something like a Gentoo or CPAN type distribution system where the real "all-stars" of development are known for having useful or interesting plugins.

The problem is. Even now this list is getting big. One of the attractions to Grails for new developers... like it or not... is that there are fewer choices. It's kind of funny but too many choices (as Scott Davis has pointed out in his "Paradox of Choice" talk) leads to people making no choice at all.

So already there are getting to be too many choices in Grails plugins. Now, admittedly, if you stuck to 1.0 and above releases you actually have only 4 plugins to choose from. But, very soon many of those "beta" plugins will be 1.0 and either way you still see them... still deal with the choice. This is an interesting problem that is going to be coming very rapidly for Grails. How do you deal with all that adoption and all that interest.

I think it will be very vital how the Grails team handles the next 18 months. They will have to find a way to deal with all the plugin contributions they get and how to limit choice intelligently.

Will they go the CPAN route? I'd like that since CPAN was (and technically still is) the best feature of Perl. Just as Ruby Gems is also a vital feature of Ruby. But, Gems lacks some of the features that made CPAN so popular. CPAN has code author based search and other web search features that allow you to read through PerlDoc (the Perl version of JavaDoc) for each module. The author recognition was not vital to Perl or CPAN but I think it helped authors to make contributions.

Will they choose an elitist mentality and have "levels" of plugins which are gold, silver, bronze? Sort of a Gentoo approach which was the best feature of Gentoo. Or perhaps it's too soon to think about yet. After all there aren't too many plugins yet...

At some point we'll need to see some categorization from the command line of plugins. We'll need search features for plugins. And, we'll need a mechanism for at least three levels of plugins... "production", "test", and "development" because we will need to allow for beta code to be distributed... and for developers to work on advanced features that rely on other plugins that aren't even released yet.

We'll need to do some level of OSGI in Grails... at least something that handles plugin dependencies and manages them. At some point the Grails ecosystem could grow large enough that you could have plugins that require other plugins. That could get very interesting.

2008-02-25

Logging in a Unit Test of a Service in Grails

Here's the scenario: You've got a grails project and you have a simple service you'd like to test. Let's say it's just something like:

class MyService {
boolean transactional = true
def myMethod() {
log.debug "MyService.myMethod() was called!"
}
}


If you were to hook up a quartz job to this service and then run "grails run-app" to test your service you would see the service happily chirruping away. Now if you were using Eclipse or some other IDE you might try to write an integration test of some kind and run that test from your IDE. You'll get an automatically generated test for that service if you used the grails commands... let's say you edit it so the test looks like:

class MyServiceTests extends GroovyTestCase {
void testMyMethod() {
def myService = new MyService()
myService.myMethod()
}
}

Now try and run that from your IDE. The test may fail with...

groovy.lang.MissingPropertyException: No such property: log for class: MyService

... what to do?

Grails is injecting the "log" property for you. That means if you want to test that class outside of Grails you'll need to do the same. So, you could do this:

import org.apache.log4j.*
class MyServiceTests extends GroovyTestCase {

def myService
def log

void setUp() {

// build a logger...
BasicConfigurator.configure()
LogManager.rootLogger.level = Level.DEBUG
log = LogManager.getLogger("MyService")

// use groovy metaClass to put the log into your class
MyService.class.metaClass.getLog << {-> log}

myService = new MyService()
}

void testMyMethod() {
myService.myMethod()
}
}


Now if you run this in your IDE you'll see your service pleasantly chirruping away in your IDE console window.

2008-02-21

Why do we write software?

I feel I have to ask: Why do we write software?

I ask this because I think the why gets lost too easily. I've recently worked on a project that modeled a name and email address in JSON like this:

[
["PRXYY_298_NAFR","Bob",""],
["PRYXY_LARFN","Roberts",""],
["PRH_2810_EMA","bob@email.com","email"]
]

... why do that?

I suspect that this kind of tri-associative array allows for type information to be included in a JavaScript model. The problem is that the data thingy (because that sure ain't no object) is no longer human readable.

But what is worse is exposing this data model in an API to use as a service. This is basically screwing over the integration developer. I can see how you could have easily modeled the JSON object as:

{
PRXYY_298_NAFR: "Bob",
PRYXY_LARFN: "Roberts",
PRH_2810_EMA: "bob@email.com",
}

... and then had a server-side mapping map "PRH_2810_EMA" to "email" on the fly. Even better would have been to use human readable names like "email" and map those to values like "PRH_2810_EMA" if you needed to server side.

Why do it?

I suspect this makes the original system designer's job easier on some level. No thought was given to system integration or how to make data import/export easy. Instead we are working with something that was easy to code but hard to use.

And, that circles back around to "Why do we write software?"

It clearly isn't to make the programmer's life easier is it? The programmer should be trying to make their user's life easier. After all isn't that why a programmer even has a job?

I mean "programmer" from the perspective of the one writing the program or API... and user being the person who is going make use of this product later. That means as a programmer I'm the user of PHP, Python, Perl, Ruby, Java, Scala, Groovy, or other technology. It means that if I write Rails, Grails, Maven, CakePHP, JSF, or other framework I'm using a programming language and creating tools that other programmers will use themselves. The role of programmer and user can switch. I could write an API then have to use it later.

So you would think that being a user of programming tools themselves the designer of our tri-associative array would have some sympathy... empathy... care for... the user of their tool since they are so very similar people. But instead of thinking about why the tool exists and who is going to use the tool our programmer chose the path that would give them the easiest success.

I don't like that very much.

As programmers our job is to do the hard things so our users don't ever have to care. The simpler we can make very hard things seem the better we are doing. For example Google probably has one of the most powerful and complex search engines on the planet. It is clustered and redundant and complex and beyond many programmer's or user's comprehension. Yet to use it you type text in one box and hit one of two buttons.

The user experience is simplified to almost a ridiculous level.

The Macintosh is like this too in places. And, so are some places in Windows. And, so are some places in Linux. Each one of these systems has traded easy in one place for hard in another. For Macintosh... hardware is harder... for windows security is harder... for Linux desktop user experience is harder. In Macintosh what does work works well and without a manual... in Windows you never wonder "will it work with windows?"... in Linux you never wonder if it will scale well or stay secure.

Each has taken a specific user experience and simplified that particular "most important" case.

So I ask you: What is your most important case? Why are you writing this software? Why will anyone bother to pay you? What would cause them to not pay you?

Features should be designed and implemented by order of priority.

So maybe my tri-associative-array friend never saw integration as a priority. But, we should have. And that should have meant we didn't pay him and instead paid for someone who aligned with our priorities.

And that is my big thought for today: Ask why you are writing software and ask whether you should write it at all first.

2008-02-17

The Singularity is Ni

Recap: The technological singularity is the moment when human intelligence finally exceeds that of machines.

Wait. Sorry.

The technological singularity is the moment when intelligence finally exceeds human machines... no wait.

The technological singularity is the human that finally exceeds the moment of machines.

Uh, that sounded profound at least.

Sorry. I've taken such a long break from thinking deeply I've forgotten how. I'll be back soon.

.... and what is that thing up there?

2008-02-06

Grails 1.0 is out

It looks like Grails 1.0 is officially out. If you don't know what Grails is go check it out now: http://grails.org/.