Rambling On My Mind
I got ramblin', I've got ramblin' all on my mind

Thu, 11 Aug 2005

Fulgora 0.2

I have released Fulgora version 0.2. It can be downloaded here.

There are quite a number of changes:

* Removed the configuration.pnut file for setting up the ActionManager, this is advanced usage and it should not be that easy to change
* Changed the exensions for the Shows and the Prepares to .show and .prepare.
* The ActionInterceptor can only be used as a Filter from now on
* Requesting an Action is done by giving the extension-less action name
* defining action sets is a lot more intuitive right now

These changes where done to simplify and straighten out the framework even more and were driven by a presentation of Fulgora I did at my new job. The current roadmap looks like this:

0.3: Maintenance release: provide full clean up, getting the extension points and abstractions right, test coverage and structured documentation
0.4: First release with Eclipse plugin support and component strategy
0.5: Public release with movie, article, ...

15:39 PDT | /Java | permanent link

Tue, 14 Jun 2005

Axiom: The Axis Object Model

Well, I guess that explains all of my problems with Axis: their developers have lost it. They have now launched something called Axiom, a DOM-oriented intermediate XML data structure. We already have quite a few of these, they are called DOM, and when you don't want to lose it yourself, XOM. Now we have to learn another one, and, by a first glance on the code, they managed to make it look actually worse than DOM. Evidence:

OMElement documentElement =
OMFactory.newInstance().createOMElement(
    "MyDocumentElement",
    "http://chinthaka.org",
    "myPrefix");
documentElement.setValue("Sample Text");

Sheesh, we can only hope for JAX-WS 2.0 to rescue us from this.

07:11 PDT | /Java | permanent link

Sat, 11 Jun 2005

Introducing Huts 1.0

'Huts' is mash up of Hibernate and Struts. It consists of a couple of classes that will ease development when using both together. The name was chosen for it's non-existence in the Java space and the dream of a future filled with 'Java the Huts'-references. The ideas for it come from discussions with Gregory Vandenbroucke, Kwinten Tobback and Julien Herfurth on the zen of web development, and why it has to be this hard. It logs using, shrug, commons-logging because Struts and Hibernate do so. A public CVS is not yet available, just the binary and source jars and some javadoc. I am getting it registered at dev.java.net but that seems to be a more difficult process then it used to be...
So let's go over the classes:

HutsFilter

This is a common implementation of the one-Session-per-thread pattern that exists already for a long time and I already talked about over here. In this version it is now safe to run multiple instances of in the same ClassLoader. It has some easy extension points to override its' behaviour when opening and closing Sessions. It has 2 modes of operation: in and out of a servlet container. When instantiating one with the constructor that takes a SessionFactory as a parameter, you can start it to be used in a test or any other POJO-like environment. Of course the basic use is to use it as a Filter in your webapp, where it takes an init-param called 'configuration' and the location of the Hibernate configuration to use as value. When it is 'active' you can call HutsFilter.getSession() and HutsFilter.getSessionFactory() pretty safely thoughout your code. When something out of the ordinary happens, like a DataSource that is closed, an unchecked CreateSessionException is thrown. This class is not bound at all to Struts so it can be used in any webapp context without any problems. It does rely on commons-beanutils though, a behaviour you can avoid by overriding and emptying registerHutsConverters() in a HutsFilter implementation.

HutsConverter

This is a Converter for use with the commons-beanutils environment and needs HutsFilter to be active. When the static method register(SessionFactory) is called, which is done by default the HutsFilter when being used as a Filter, it will register itself as the converter for all of the mapped classes in the given SessionFactory. When asked to convert a String to an object for one of these classes, it will look upon the String as the Stringified identifier of the mapped class and load, and return, the mapped object identified by it, connected to the current Session. This is a long explanation for being able to do:

<html:text property="bridge" value="${myActionForm.bridge.id}"/>

Which will, when submitted, load up the Bridge object identified by the id and set it as a Bridge on the 'bridge'-property of the ActionForm. Note that you have to specify the value of the property in the Struts tag as it will not call this converter when writing out the value of the Bridge, although this functionality is written as well, Struts will just do a toString(). Also note that this should work with any beanutils based web framework, like Spring MVC, but I haven't tried it yet.

The class is a small hack with huge consequences, especially is used in parallel with:

HutsRequestProcessor

This is the most controversial, wink to Kwinten, of the set, and at the same time one of the most powerful. It assumes a development structure where Hibernate mapped classes extend ActionForm and are used as thus in some Struts actions. This custom RequestProcessor, when registered as 'processorClass' in your Struts configuration, will detect these kinds special ActionForms and try to load them in the Hibernate Session, before their properties are being set by Struts. It will listen to a request parameter with the same name as the Hibernate identifier and use its' value to find the appropriate object. It allows you to make CRUD actions very easily: you only have to create the JSP's and a SaveAction that calls HutsFilter.getSession().saveOrUpdate(actionForm), all the rest is done automagically.

An example: imagine you have a Hibernate mapped bean called Bridge that has an identfier called 'id' and a property called 'name'. In the detail-action of this bean you just have to make a JSP like:

...
<html:form action="/bridge/save.do">
	<c:id test="${bridge.id != null}">
		Id: 

And a Struts configuration like:

...
<form-bean name="bridge" type="org.futurestreet.huts.examples.Bridge"/>
...
<action name="bridge" path="/bridge/detail" scope="request" forward="/bridge/detail.jsp"/>
<action name="bridge" path="/bridge/save" validate="true" input="/bridge/detail.do" scope="request" type="org.futurestreet.huts.examples.SaveAction">
	<forward name="success" path="/bridge/detail.do"/>
</action>
...
<controller processorClass="org.futurestreet.huts.HutsRequestProcessor"/>
...

When an 'id' parameter is given as a GET parameter, the HutsRequestProcessor will load the matching bean and fill in the name box. When saving, it will do the same and then set the 'name' with the value given in the request, after which, in your own, and very likely generic, SaveAction it will persist the change. Right now it can only be used correctly in actions with request-scope, something I want to fix as soon as possible.

PS: Commentators, especially the anonymous ones, I don't want to get in discussions about dirtying up your precious Hibernate POJO object model with ActionForm extensions. For a lot of projects, you shouldn't care: the coupling is just a couple of characters, 'extends ActionForm', get over it. For the people who are now all red-eyed of rage, I am planning a decoupled version as well...

11:32 PDT | /Java | permanent link

Sun, 29 May 2005

Re: Neat ThreadLocal Trick

This started out as a comment on a previous post, but I thought it deserved to be lifted to the front page. It is a response to something that my good old friend Anonymous mentioned, in his, as usual, eloquent style:

You blogged about this? This solution has been around since Hibernate 1.x (maybe earlier).!

Yes, I blogged about this: have a look here :-) I will be the first to admit that this solution already is around for ages, I remember doing something pretty similar with OJB quite a number of years ago, but after looking at yet another code base with Sessions being passed on through everywhere, I thought it was worth mentioning yet another time. I am sorry if this behaviour offended your intellect in any way.

Furthermore, your logic with regard to not using other projects/libraries is flawed. ... No one said you have to use everything in Spring. And struts?! Jeez, don't get me started!

I am not really sure what you mean with "flawed logic". I'll walk you over some of my premises:

  • I can get an external Struts developer in a day, introduce him the next and let him be productive around 11AM.
  • Some developers, unlike me, use IDE plugins for their mappings: guess which framework has any/the best ones available? See also for the rest of tool support.
  • Struts 1.* is aging more and more like Java: it has the potential to become, and maybe already is, a mature legacy framework.

We also have done some pretty cool things as well to ease up Struts/Hibernate development even more: something I will blog about later, check it out: it feels good.

To wrap up: don't get me wrong: I think Spring (IoC, MVC and AOP) is cool: I like it, I use it, but not in this project: move your hammer, slowly, away from the screw.

Apparently, you solely make your determination if something is usable based upon whether it is in the hibernate.jar.

Yeah, that jar really annoyes me: it has been dictating out internal code policies for too long. The word 'whatever' materializes once again...

09:28 PDT | /Java | permanent link

Sat, 28 May 2005

Neat ThreadLocal Trick

At my current job, at DAD, we try to be as conservative as possible in the technologies we use. So no Spring, no Ruby on Rails and we try to keep the AJAX magic to a minimum. The main reason for this is that we want developers, internal and external, to be as productive as possible as quick as possible and to straighten the learning curve to switch projects.

The framework that we are pushing right now is based on standard Struts, Hibernate and some tag libraries. I also introduced some neat little tricks that gives you some pretty cool cross-cutting features, just using the ThreadLocal class. It's the kind of code I love to write: simple, small and obvious when you have started using it. The other developers seem to like it as well, because it is non-intrusive to their work and, well, only has benefits.

One example: I'll first show the code, and then walk through it:


//omitted the imports
public class HibernateFilter implements Filter {

    private static SessionFactory sessionFactory = null;
    private static ThreadLocal sessions = new ThreadLocal();

    public void init(FilterConfig config){
        sessionFactory = //build a new instance...
    }

    public void doFilter(..., FilterChain chain){
        chain.doFilter(...);
        closeSession();
    }

    public static void closeSession(){
        Session currentSession = (Session)sessions.get();
        if (currentSession != null){
            try{
                currentSession.close();
            } catch (HibernateException ex){
                //log the ex
            }
        }
        sessions.set(null);
    }

    public static Session getSession(){
        Session currentSession = (Session)sessions.get();
        if (currentSession == null){
            currentSession = createSession();
            sessions.set(currentSession);
        }
        return currentSession;
    }

    public static Session createSession(){
        Session session = null;
        try{
            session = sessionFactory.openSession();
        } catch (HibernateException ex){
            //do something intelligent
        } catch (SQLException ex){
            //do something intelligent
        }
        return session ;
    }

    public void destroy(){

        try{
            sessionFactory.close();
        } catch (HibernateException ex){
            //log
        }
        sessionFactory = null;
        sessions = new ThreadLocal();
    }
}

When the filter is initialized the SessionFactory is started and whenever you call getSession() within the scope of a request, the same Session will be returned. When it doesn't exist yet, a new one is created. When the request finishes: the Session 'attached' to it is closed. Note that when you do not call getSession() anywhere in the request, nothing happens, which means that you can map the filter over your entire webapp, and there will be nearly no overhead when accessing static content.

It follows the one-Session-per-Request pattern, but doesn't require you to pass on requests and/or Sessions through all of your code. There is no injection needed from a container, no AOP configuration and nearly no code to do this. For the testing crowd: it is very easy to add a custom init() that would instantiate the static SessionFactory with a special test implementation.

08:07 PDT | /Java | permanent link