2007-12-19

Fun with Groovy and the Reflection API

Here's the scenario: You've got dates in the format "MM/dd/yyyy" to be parsed and turned into a real Date object. You would parse the date like so:

public Date format(String str) {
def format = new SimpleDateFormat( "MM/dd/yyyy" )
return format.parse(str)
}

public String format(Date date) {
def format = new SimpleDateFormat( "MM/dd/yyyy" )
return format.format(date)
}



And you have hundreds of collections of Java and Groovy objects that your library could be potentially mapping from hashes that look something like this:

["foo":[ "id" : "5", "started":"12/11/2007", "name":"bob" ]]


You could write a switch statement for each of these... or you could go and ask the class defintions for what the types of foo.id and foo.started are. But if you do this:

class Foo {
Long id
Date started
String name
}
def foo = new Foo()
println foo.started.getClass()

... that println will print "null" because the started object is set to null. So how do I know if "started" is a date or not? I need to know the type on the other side of the "started" member. It would be nice to have a reverse mapping I could use... so I wrote this:

def getTypeMap(Class clazz) {
def typeMap = [:]
def members = clazz.getDeclaredFields()
members.each( {
m ->
typeMap[m.getName()] = m.getType()
} )
return typeMap
}


... now you can ask the type of a field like so ...


def classOf(Class clazz, field) {
def typeMap = getTypeMap(clazz)
if(typeMap.containsKey(field)) {
return typeMap[field]
}
else {
return null
}
}


... to get the type of the field on the class you are working with... in a loop you would...


def params = ["id":"5","started":"12/11/2007","name":"bob"]
def foo = new Foo()
params.each({ key,val ->
def clazz = classOf(foo.getClass(),key)
if(clazz && clazz != Date.class) {
foo[key] = clazz.newInstance(val)
}
else if(clazz) {
foo[key] = (Date) format(val)
}
})


Presuming you knew that all the values of "val" were strings and all the members in "Foo" had constructors that could handle a string argument intelligently. I cache up the type map else where so that the real production classOf doesn't build a new type map on each pass.

But now I can map from arbitrary strings into real objects and back without having to specify a "mapping" for each object.

Seven Sins of Bad Groovy Programming

Jörg Staudemeyer has posted on the groovy-user forum at nabble a list of seven sins committed in groovy and why they are bad. A good read for anyone new to groovy.

2007-12-18

Single Sign On with JBoss Portal and Active Directory

No one has asked for it but I've begun work on a SSO project when I'm between official projects. I discovered the power of Acegi and CAS. I have an install of the JBoss portal as well and that requires its own set up too... however it is looking like we are going to use Joomla instead.

I began with understanding how to talk to an ldap server (in my case Active Directory). Once I understood how to query LDAP I began searching around using my groovy scripts to find the object classes, and specific names I would need inside my CAS configuration.

I then followed this tutorial for CAS to authenticate the users:

Next I built in the CAS client into JBoss portal using this wiki page's instructions:

Finding the specific settings were hard. In particular I had to muck about with the ldap_identity-config.xml deep inside our jboss-portal.sar file... it turns out our AD setup is somewhat "special" and needed some extra care beyond what is in this page:

I have no idea how I would have figured out how to do that kind of configuration without that wiki page.

Once I managed to stitch together both sets of instructions I could have my users authenticate via CAS and then the portal would query roles on its own against Active Directory.

Next I'll investigate how to bring Groovy and Grails into this mix. I'll have a project for delivery in March that will need to hook into this SSO system... and likely subsequent projects to link into the CAS system using PHP and Perl.

2007-12-12

BPM is mostly wrong

In response to:
The Seven Fallacies of BPM

Mentioned in "The World is Flat" book Business Process Modeling systems were supposed to deliver businesses with a glorious future in which Business Analysts could model processes without the need for a programmer's intervention.

The problem is that the modeling process itself is core to application development and utterly central and important to a properly functioning application. You would no more have a Doctor design your house than you would a Business Analyst design a Database or Application. The Doctor is concerned with much different sets of concerns than an Architect is. The Doctor is concerned about wheel chair access and ventilation while the Architect is concerned with whether the building will stand up to a storm or earthquake.

While both a Doctor and Architect could collaborate to create a house you would not have a Doctor build a house unassisted. If you did you would be inviting disaster. And, you would be offended if I suggested that you take dietary advice from an Architect. That would be absurd.

It is true that many small projects are released without the help of a specialist. I'm certain many buildings are built without an Architect... and many diseases are overcome without a Doctor. But, you should ask yourself what your project is? Are you trying to produce a professional product or are you just "hacking around" looking to make something that works? Do you want to create "professional" systems or just "hobby" systems. Are you producing a reliable car or are you creating a dune buggy in your back yard?

If you can honestly answer that the project you are producing is a "buggy" then by all means forgo the professional assistance ... but don't kid yourself... that's not a Toyota you've got.

2007-12-08

Learning the Eclipse RCP

While I'm learning grails I'm also learning the Eclipse RCP. I'm hoping to merge the two efforts at some point.

2007-12-07

telecomputational

Heard in conversation just now:

You have a telecomputational device don't you?

--Billy Howell


It's the dawn of a new era.

Grails 1.0-RC2 sprites and stogies

So, I've run on over to check out the Grails 1.0-RC2 release and see if all my favorite bugs were fixed. They were! And there were birds chirruping and rainbows and a unicorn ... and a sprite lit a fresh stogy for me and one for Bender. Then I tried to do something a little unusual. Should I? Dare I? Yes.

I tried to do a one-to-many mapping where the "one" side was a Groovy domain class and the many side was a JPA annotated class (You know an EJB3 entity bean). And it failed. Oh, the misery and woe! Well, okay it's not quite that bad.

So the lesson learned children? Don't do drugs, stay in school, use JPA or use GORM, be careful using both. I have filed this bug hoping that next time the stogy is a fine cuban cigar: GRAILS-1983. Bender likes fine cigars.