Tuesday, March 20, 2007

Wicket and Groovy

I attempted to explain the concept of what I'm working on in a previous post, but its a little convoluted, and gets into implementation details, etc. Not very clear.

I'm getting ready to announce the project on a few mailing lists, so in preparation, I'm going to attempt to explain the idea again. Please bear with me...

Groovy, Grails, Rails, recent interviews and feeling a little like Old Gill...

I love Java. I've loved Java for a long time. I started coding Java in college, when it was version 1.0. Try this out. Its an asteroids clone I wrote. If you can dig up a Pentium 75, it will actually work.

For the past several years I've been running a small technology group building fairly heavyweight enterprise applications for a financial company. A relatively sheltered existence, to be sure. They move very slow on to new technologies. For my own part, I read a lot, but I'll admit I stuck pretty much to the Java realm. Maven, Hibernate, JSF? All over it. Ruby and Rails? Didn't even look.

So, I've been interviewing lately. It turns out that not everybody thinks Rails is mostly hype (as I did). Specifically, I spent a day at a company called Cyrus Innovation (cyrusinnovation.com). Its a small group of very intelligent people who actually believe in agile techniques, pair programming, do a lot of Java, and absolutely get into Ruby and Rails.

At 31, my interviewing experience left me feeling a little like Old Gill (simpsons reference). The prevailing attitude, at least in some areas, is that Java is old and Rails is the next big thing. That would be fine, except I really can't fathom tossing away such huge piles of quality, tested code that exist in the Java space. Also, Java is a great language for certain classes of applications. Part of the value of Rails comes from the language dynamics of Ruby, but a lot of the advertised productivity improvement comes simply from the framework. In short, there's no magic going on. Good ideas, but ideas are transferable.

It didn't take long to stumble onto Groovy and Grails. Its like an intellectual slap in the face for a long time Java programmer. Groovy is a dynamic language, syntactically similar to Java, which can seamlessly inter-operate with Java. Grails is a Rails-like framework built on top of Groovy. Assuming some time for stabilization and optimization, it levels the playing field in my mind. You can use the platform you're currently on, and extend it with a significantly more expressive language where needed. Not throwing the baby out with the bathwater.

Groovy and Grails are behind in terms of IDE support and general "smoothness" of development. I personally think Groovy is a fantastic technology, and my biggest concern is it simply won't get the time and effort needed to make it a first class option for the Java platform. It should, though. Java and Groovy together is a fantastic combination.

Wicket?

Right before I started with the dynamic languages, I had first tried out Wicket. For the past year or so I've been working with JSF. First on my own, then with my soon to be released major project. JSF is more productive than simpler options like Struts, and has some major industry support, but many things with JSF feel unnatural.

I had read about Wicket here and there, but had mentally stuffed it into the, "Oh man, another web framework" category (ie. the circular file). I finally gave it a shot, though. Yep, I was totally wrong. Wicket does some things in a way that seems, in retrospect, obvious. I think it has the freedom of not trying to be everything to everybody, and not having large committees making decisions, as JSF has to deal with. Its a great technology for the 98% of web applications that aren't be hit by thousands of users concurrently. Its a component framework, like JSF, which is nice for creating more complex user input constructs. Its page creation and linking features, however, are much better than Struts and JSF. By "much better", I mean respectively: Struts, JSF, Wicket -> walking, skateboard, ferrari. The way models can detach and reattach data objects is just awesome. I'll stop there. In summary, I like it.

So, now I'm all big on Groovy. What I disliked about Rails, and what I like about Groovy and Grails, is that you can use Java's existing code base in your new apps. Along with that, as Wicket really is great technology, I want to use it from Groovy code. Can you use Wicket and Groovy together? Yes, but its clunky. Why? Well, if you compile your Groovy into classes, it'll just work. That's good. However, Wicket relies on anonymous inner classes all over the place. You can create regular classes and override methods in them, but anonymous inner classes make that process much easier. Works great in Java. Groovy, however, doesn't do anonymous inner classes. Groovy uses closures, which are sweet as well, but you can't use closures with Wicket (obviously. If that wasn't obvious, you should probably stop now because you're going to be really lost soon). My goal with this project is to make Wicket programming with Groovy at least as easy as it is with Java, and hopefully easier. Besides, of course, the inherent expressiveness of the language itself.

Wicket Groovy Builder

Groovy has a concept called a builder. See here...

http://www-128.ibm.com/developerworks/java/library/j-pg04125/

The idea came to me to use a builder when I saw the SwingBuilder. It allows you to build a Swing app in groovy, with significantly simpler code. The Swing component structure is roughly tree shaped. Well, that's the first thing I noticed about Wicket code. It looked a lot like Swing code.

Simple concept. Write a builder implementation that build a Wicket component tree. Sounds easy, but its fairly complex. I won't go in to it, but lets say I do some things with closures that they weren't meant to do. Over the next couple weeks I'm going to be working on the project as well as the documentation, so hopefully I'll have some more detail on the implementation soon.

Originally I started doing this as a seperate project, but Eelco Hillenius from wicketstuff contacted me about the project. He had done some work on the 'wicket-groovy' project from wicketstuff, and proposed I move the builder code in there. Here's the website...

http://wicketstuff.org/confluence/display/STUFFWIKI/wicket-groovy

Right now my code is in the 1.3 branch only. You can see the latest subversion tree at...

https://wicket-stuff.svn.sourceforge.net/svnroot/wicket-stuff/branches/wicket-1.3/wicket-contrib-groovy

Does it help? Here are two screen shots of roughly equivalent code:

Java Version



Groovy Version



The larger the form, the more obvious the benefit.

Future Plans

The biggest thing is just using it in some applications, and writing some better test cases. I was banging my head against a wall today and yesterday over some pretty major stuff, so I'm sure there are a few other issues in there somewhere.

There are certain places where optimization would help significantly. Specifically on the dynamic class generation. Its generating a new class on each run. This isn't good. I have to sort out a problem with the Closure's owner, and then I can re-enable class caching. Today, though, a production implementation would probably run into trouble not too far down the road.

I haven't looked at the wicket-extensions at all.

I'm going to add GORM support from the Grails package. That is a really cool technology. Alternatively, we might be able to use Wicket as a render technology inside a grails app. Anybody know if this is possible? I have very little Grails experience.

Simplify the IDE and build procedure. This is one of those things that quickly turns off new users. Frustrating build experiences are bad.

Add some template applications. Set it up so getting off the ground takes little effort.

If anybody would like to pitch in, let me know.

14 comments:

Graeme Rocher said...

Hi,

Sounds like an interesting project, Grails is actually a Spring MVC app under the covers and all the normal servlet API objects are available.

If you're able to give me an example of how you would integrate wicket into a servlet as a rendering tech then I can help you integrate Wicket into Grails.

Grails provides a lot of infrastructure code around persistence, reloading and MVC that it would definitely be worth looking into it before re-inventing the wheel.

Let me know if you want to chat, email me at graeme.rocher@gmail.com


Graeme Rocher
Grails Project Lead
graeme.rocher@gmail.com

Anonymous said...

Looks great! What's your HibernateListModel?

Kevin Galligan said...

HibernateListModel is from databinder:

http://databinder.net/

I'm going to do a new set of examples that use standard components, and another set that get into hibernate, but keep that seperate. I think both together just confuses the situation.

There are only so many hours in the day, though, so some things aren't quite where I want them.

By way of full disclosure, I took a little artistic license in that example. The original has AbstractReadOnlyModel for the name label, and I simply replaced it with PropertyModel for my example. I'm actually not sure why they used AROM in that spot rather than PropertyModel, but that's the code I had, so I went with it. The AROM usage has a lot of extra code just for the anonymous override, but to me it was a great example of bloat.

Anonymous said...

Yeah I know a thing or two about that Databinder. ;) I was so focused on the Groovy code I didn't even notice that the Java code was my own! But I don't think it's a good idea to use a property model instead of a pull model there; it works out to PropertyModel(new Model((Serializable) DataPage.this, "expression")). Your component hierarchy will be serialized a second time, unless there's some Wicket code that watches out for that situation (doubt it).

That goes back to the same problem of not having anonymous subclasses, which are just as useful in throwing together pull models as they are for component subclasses. That's probably a job for another builder, or some other use of closures. Anyway, I'm thrilled that you're working these things out and look forward to adding a Groovy example in Databinder.

Actually, I wouldn't hesitate to move all examples and all of my programming to Groovy, but as I understand it it's not going to be possible to annotate @Entity classes with it anytime soon. (?) I looked at GORM, but I'm happy enough with H.Annotations, and HQL, and the criteria API, that I don't feel compelled to switch. Seems like, over time, the Groovy annotations situation will resolve itself.

Kevin Galligan said...

Now that is funny! Small world.

Example code is from some playing around I did with databinder. I think I stopped mid-thought with that one. The implementation is sub-optimal, for sure. Another reason for a simpler example, at least for the WicketBuilder. Don't want to mix everything up.

As for the Model anonymous overriding, that was another thing on the todo pile. Somewhere in the back of my mind. The builder could recognize the Model as an instance of IModel, and add it as such, but do the method spoofing with closures the same way. I had some concern about confusion between component and model name resolution, but for the most part I think it would be ok.

I was trying to asses the practicality of that as well. On the groovy mailing list I've been back and forth with Jochen Theodorou on using specific groovy subclasses as opposed to this dynamic overriding deal I've got going on. An example would be like the following:

public GModel(Closure getObject, Closure setObject){code here...}

Another possibility is to get fancy and do something with the metaclass and invokemethod, but since the code would be called from Wicket, which is Java, I have a feeling it would skip the metaclass layer in many cases (this is why I didn't use that for the Component builder portion. I tried).

So, yeah, models are on the radar. I'm still pretty new to Wicket, Groovy, and Databinder specifically, so I'm going to do some bad stuff along the way. We'll see how it goes.

I like the annotation Hibernate stuff, but I like GORM too. I think setting up the code so either could be used would be pretty sweet.

What I love most about all of this stuff is that you can move back and forth between Java and Groovy/GORM/Grails style without trashing your whole stack and code base. I wanted the Wicket implementation so you could back out the Groovy version and recode a full Java version on heavily used pages if you ever felt the need (I don't think you ever would, but its nice to feel like you could).

Kevin Galligan said...

I forgot to mention something. As far as moving all of your examples to Groovy and the @Entity situation, you don't really have to. That's the beauty. You can code your Page objects in Groovy with the builder, but use your standard data access code in Java and use Hibernate annotations. That's what I think is so compelling about Groovy in general. You can do certain parts in Groovy, and other in Java. Whatever is best in that situation.

Groovy and annotations? That would make sense, but there's a cutoff point here somewhere. Like with Java and Closures. I think having both languages exist and simply improving tool and class loader support is the way to go, rather than trying to make Java into a dynamic scripting language (and vice-versa for Groovy I guess). Annotations in Groovy? Ok. Closures in Java? Ok. Optional typing in Java? No. Simplified bean access in Java? Hmm. Maybe. I just feel like its not the end of the world to have both and let them focus their strengths on what they each do best.

That was a huge tangent.

Anonymous said...

Hi, I think it's really a nice idea to combine the flexibility of Groovy with the simplicity and power of Wicket. Though I'm just learning Groovy, I've worked with Wicket for some time and it's been really helpful in the apps I've worked on.
Are you think in using Groovy to create the Wicket components or maybe to replace the presentation layer used in Grails?.

Best Regards,

Jaime De La Jara F.

Kevin Galligan said...

First, to n8han...

Ok. I put some thought to it. There's IModel, IValidator, and IBehavior, that can all be added to a component, and one might conceivably want to do that in the builder tree.

BuilderSupport defines:


createNode(Object name)
createNode(Object name, Object value)
createNode(Object name, Map attributes)
createNode(Object name, Map attributes, Object value)

Only the two with 'value' parameters are used with the WicketBuilder. That's because the Component objects need a key value. So, the simple version will work as follows. If one of the other two are called, we'll assume its either a model, validator, or behavior. Then apply a process similar to what happens to Components (override on closure name, yada yada). Then, add that to the parent Component (or whatever type is appropriate).

Sounds easy. I'm sure there will be some huge problem along the way, but that's what programming is about.

...and to Anonymous...

In summary, I'm trying to be as unambitious as possible, while not being too hacky. That's an inspiring mission statement, right?

The builder is just a convenience tool for creating standard Wicket Component trees. You could do everything its doing in Java, or even in Groovy directly, although Groovy lacks anonymous inner classes (which is what drove the builder idea to begin with).

If you look at the first comment, that discusses grails and wicket. I still have to look into that. I think there will be trouble between what Spring MVC is doing and what Wicket is doing. However, there are many levels at which integration could happen.

The long answer is I'd like to bootstrap GORM to use it outside of the Grails stack and in a small Wicket-based app, hopefully under maven's hood. The logical opposite of that is I'd like to be able to use Wicket inside a grails app, seamlessly alongside standard Grails code (gsp?). I think the component model of Wicket is very useful and there are classes of applications that are easier with that, and vice-versa.

The short answer is I find the fragmentation of different projects frustrating, and I don't really want to add to that. So, the goal is to let Wicket play on both sides of the fence and add to the total, rather than increasing the division. Sounds nice. We'll see how it goes.

Anonymous said...

"You can code your Page objects in Groovy with the builder, but use your standard data access code in Java and use Hibernate annotations."

Right. I guess I'm hung up on getting those beans into Groovy in order to drop, once and for all, the need for boilerplate getters and setters. I think they would stick out even more if the pages were in cleaner looking Groovy, and then I would find myself trying to tie into GORM and not getting any sleep. But wait, maybe we're closer than I thought!

Kevin Galligan said...

Well. You could code a base class for each bean in Groovy, then override that in Java and put the annotations on it.

Yes, that's a joke.

Annotations in Groovy make sense. That will be cool. That brings up another things that bothers me while coding this thing. Groovy is moving so fast, by the time I'm done there will be some great additions that make a bunch of stuff unnecessary.

As for getters and setters, they never bothered me till I didn't need to have them. As I step back into my big Java-only project, I am annoyed with them big time.

Julian Klappenbach said...

From my own perspective, I see a lot of power in letting Grails define the service layer. Having MOP available for dynamic method instantiation is a huge win. Closures are fanastic for encapsulating business logic for distribution among the various entities in the system.

I've heard of some projects in RoR where they're doing just that. RoR is taking care of the service layer, business logic, etc, but presents a facade for other presentation technologies to handle rendering.

So, when I first thought of doing the same with Wicket and Grails, I was excited by the notion. However, one caveat immediately occurred to me: Spring MVC is fairly rigid in terms of request, response behavior. If it's the same framework I've used in the past, it has a well defined page navigation strategy (document centric). This is in stark contrast with Wicket, which, if anything, is Panel-centric. I've designed entire applications without invoking a single up-front http request. Ajax calls swap out panels, much as a Swing-esque desktop application.

While this strategy works marvelously for business class applications, it defeats the action-based request-response driver of Spring's controller -- unless the controller can be triggered by Ajax calls.

If not, Wicket is perfectly capable of handling web applications with the old style http transaction. It's also capable of supporting document centric architectures.

I'd just hate to see those as limitations.

Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...
This comment has been removed by a blog administrator.