Archive for May, 2010
So I decided I needed to be a bit more Java savvy. One of the most common technologies you’ll encounter when developing is so-called Object Relational Mapping or ORM. The concept here is really simple, ORM lets you treat rows in a database like they were real live language objects, so if you fetch objects you’re really fetching database rows and if you update objects you’re really updating database rows. The concept is pretty simple. Somehow, though, the implementation is really nasty. And I mean really, REALLY nasty.
I set out to learn probably the most popular Java ORM, hibernate, using a hibernate tutorial. The tutorial is pretty decent if you overlook the fact that it doesn’t actually work and you need to search the jboss forums for fixes to the Maven POM file (what is that anyway?). Well then there was the fact that I couldn’t actually get it working. In truth it was probably my fault, I probably got one of the 17 steps wrong in the 30 page tutorial, or maybe I did them out of sequence or something. But I got close enough that I decided that if I absolutely, positively had to get it working I probably could.
After this experience I can’s say I’ve become much more of a Java fan. I started to take a look at some of the other technologies involved in building Java apps and my head began to spin. Do I use hibernate or should I use JPA? Do those things even do the same thing? Do I need to use JTA with either of them? Is struts a part of tiles? Other way around? Or are they competing technologies? There are at least 3 logging frameworks in Java that seem to have good traction, which one should I use? Is TestNG better than JUnit? Does it really matter? A funny note in the Hibernate tutorial is that Hibernate supports *BOTH* c3p0 and proxool as JDBC connection pools (What?), but you should positively under no circumstances use the default JDBC connector that ships with Hibernate because it’s a piece of crap.
I’m ready to fly the white flag, this stuff is just too much for me. Call me a bad developer but I just don’t have the patience for all this nonsense. They have a term for this, “yak shaving”. Reminds me of the bad old days of UNIX, when you were thrilled if “configure; make; make install” didn’t require you to edit source code.
On day 2 of my Java adventure I decided to figure out Roo, mostly because I couldn’t figure out what it was or why anyone would use it. And I guess somebody must think it’s pretty important because it’s what Ben Alex showed off at Google IO. (Ben has a love for expense reports that borders on unnatural but it’s still a pretty good demo.)
Roo is a “convention over configuration” tool, which is just a fancy way of saying that it makes a bunch of decisions you really shouldn’t care about and it makes them automatically. No more scratching your head figuring out if you should use JMX or JPA or JINI or JPMC or JWTF. As someone who doesn’t know or care what’s going on under the covers this is really attractive.
So I gave it a shot, not trying to follow Ben’s IO demo, but rather the online Pizza Shop demo. (I have it on good authority that Ben once tried to expense over $13,000 worth of pizzas, probably where he got the idea for the expense report app.)
project --topLevelPackage com.springsource.roo.pizzashop persistence setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY entity --class ~.domain.Topping --testAutomatically field string --fieldName name --notNull --sizeMin 2 entity --class ~.domain.Base --testAutomatically field string --fieldName name --notNull --sizeMin 2 entity --class ~.domain.Pizza --testAutomatically field string --fieldName name --notNull --sizeMin 2 field number --fieldName price --type java.lang.Float field set --fieldName toppings --element ~.domain.Topping field reference --fieldName base --type ~.domain.Base entity --class ~.domain.PizzaOrder --testAutomatically field string --fieldName name --notNull --sizeMin 2 field string --fieldName address --sizeMax 30 field number --fieldName total --type java.lang.Float field date --fieldName deliveryDate --type java.util.Date field set --fieldName pizzas --element ~.domain.Pizza controller all --package ~.web
With this file in hand, all you’ve got to do is pipe it into Roo and after a few minutes you’ve got a working application. If we break the script down, there are 5 major things:
- Create the application using “project”
- Instruct it to use Hibernate and the Hypersonic in-memory database.
- Create entities (these correspond to database tables).
- Create the fields within the entities, and associations between the entities.
- Add a web layer using “controller”.
It’s easy to feed this to Roo automatically by just putting it into a file called, say, pizza.roo and running:
$ /path/to/roo/roo.sh < pizza.roo
Roo does all the grunt work of dealing with Maven, which in turn downloads all your dependencies (this can take a while the first time you do it), and creates lots of stub code for you. After this I ended up with 458 files which I could compile into a web app. This included a fairly complex Maven pom.xml file which I could use to do other things, such as launch the application. To do that, just type this in the root of your project directory:
$ mvn tomcat:run
You should note that this wants to launch its own Tomcat and HSQLDB. If you have local copies of either of these apps, there will be conflicts. Since I did, I decided the path of least resistance was just to shut down my system services and let Maven handle it all. After that launches you can navigate to localhost with your web browser as follows:
Success! A working (sample) app without a line of code! True I didn’t write code, but more importantly this approach seems to make data the primary concern, which I find very attractive since combining, processing and displaying data is the real value of any application.
In this example everything, including the database, runs in memory, you don’t need anything installed except Roo, Maven and your JDK. To make things a bit more interesting I decided to link this application to a MySQL database that I have running on my host. This proved to be surprisingly easy, with only one gotcha. I went back into my Roo shell and typed in:
persistence setup --provider HIBERNATE --database MYSQL --username carter
This almost worked, but I had to manually edit a field in a file called database.properties to read like:
Here “hibernate” is the name of my database in MySQL. Ordinarily you’d probably want to use things like usernames and passwords but I like to live dangerously. With that in place I launched my application again by typing “mvn tomcat:run”. I was pleasantly surprised to find that everything worked! I took a peek in MySQL and couldn’t believe my eyes, all the right tables had been created automatically! Working with Roo is a real pleasure compared to slugging it out by hand with tools like Hibernate.
I’m really impressed with Roo and think it’s one of the most interesting things going on in the SpringSource portfolio right now.