Q: What is almost as bad as a Singleton?

Posted by Dominik Tue, 06 Mar 2007 12:20:00 GMT

A: A class that has only static methods but also has (static) state.

In Java you often see XyzUtil or XyzHelper classes which only provide static methods (like, e.g., StringUtil from jakarta commons lang). These classes provide helper methods which usually act on an object which is passed along as an argument to the methods.

(Excursion: Java needs these static utilities because we can neither add new methods to a class without subclassing it and often cannot subclass the class we want to extend, like String, which is final. Ruby [and other languages] do not have this problem, since they provide the possibility to open a class and modify it or to use modules to mix in more behavior)

I don’t want to go into the question why I deem Singletons to be evil (I’m not the only one, just google for “Singleton evil”).

Now, a class which only has static methods and has a state is (imho) as bad as a Singleton, because it actually only is a Hidden Singleton, a way to work around the fact that the coding guidelines for a project don’t allow Singletons.

In the case I just stumbled upon such a hidden Singleton was used to retrieve a configuration object and to lazily create it, if it was not created before. So the first call to getConfiguration() created and stored (on a static field) a Configuration instance, and each further call just returned that instance. Now, first up, a getter should be idempotent anyway, but lets leave that aside. The class worked well in production settings. The first time the configuration was requested, it was created (which takes some time), afterwards the cached instance was returned. But during testing everything goes wrong. Using such a Hidden Singleton allows for the testing of only one Configuration. I can’t say: run this testcase with that configuration and this other testcase with that other configuration. The configuration was already loaded and won’t be modified.

So I either need a way to null the cached configuration on the Hidden Singleton, or need to get rid of it and replace it with some other pattern. What you usually want in such a setting is IoC, someone should simply set the configuration on all instances which need it (and such making those objects conform to the law of demeter, because they don’t need to fetch the Configuration from some other class). If you don’t have an IoC container, you might use a factory pattern to alleviate the pain the Hidden Singleton is causing. Use a factory to create the objects which need the Configuration. The factory can set the configuration on the objects during creation, and the configuration can be passed to the factory method (and, if really necessary, cached inside the factory until a different configuration is passed along…)

Posted in  | Tags , , ,  | no comments | no trackbacks

How to make JSF navigation rules more dynamic

Posted by Dominik Wed, 24 Jan 2007 13:22:00 GMT

Consider the following situation:

You do a post request from some form in an JSF application and want to decide on the page to redirect to dynamically. No problem, just use different “navigation-case” entries and go to different “to-view-id”s depending on the “from-outcome”.

<navigation-rule>
    <from-view-id>/pages/organisation/*</from-view-id>
    <navigation-case>
        <from-action>#{OrganisationBean.select}</from-action>
        <from-outcome>to-user</from-outcome>
        <to-view-id>/pages/user/details.jsf</to-view-id>
        <redirect/>
    </navigation-case>
    <navigation-case>
        <from-action>#{OrganisationBean.select}</from-action>
        <from-outcome>to-project</from-outcome>
        <to-view-id>/pages/project/details.jsf</to-view-id>
        <redirect/>
    </navigation-case>
    <navigation-case>
        <from-action>#{OrganisationBean.select}</from-action>
        <from-outcome>to-whatever</from-outcome>
        <to-view-id>/pages/whatever/details.jsf</to-view-id>
        <redirect/>
    </navigation-case>
</navigation-rule>

Sure, this works. It’s not exactly what I would call DRY, but it works. But what if you need to be more dynamic then that?

Just use a framework that’s more dynamic I hear you say.

Sure, I’d love to. But what if that is not an option?

I found this, this and this on the web, and putting these together gave me the following solution which I wanted to share with you:

Step 1:

Create a ViewHandler, in my case a subclass of com.sun.facelets.FaceletViewHandler and overwrite getActionURL():

@Override
public String getActionURL(FacesContext context, String viewId)
{
    String result = viewId;
    if(Util.isVBExpression(viewId))
    {
        ValueBinding vb = context.getApplication().createValueBinding(viewId);
        result = vb.getValue(context).toString();
    }
        result = super.getActionURL(context, value);
    int queryStart = value.indexOf("?");
    if((queryStart > 0) && (result.indexOf("?") == -1))
    {
        result = result + value.substring(queryStart);
    }
    return result;
}

This enables you to use EL in the to-view-id entry of a navigation case.

Step 2:

Register your view handler with the application, in my case:

<application>
    ...
    <view-handler>com.interactive_objects.jsf.crud.generic.DynamicViewHandler</view-handler>
</application>

Step 3:

Now you can do things like:

<navigation-rule>
    <from-view-id>/pages/organisation/*</from-view-id>
    <navigation-case>
        <from-action>#{OrganisationBean.select}</from-action>
        <from-outcome>selected</from-outcome>
        <to-view-id>#{OrgansiationBean.computedRedirect}</to-view-id>
        <redirect/>
    </navigation-case>
</navigation-rule>

(You can also use compound expressions like “/path/to/page.jsf?foo=#{ManagedBean.bar}”).

Tags ,  | 8 comments | 3 trackbacks

Page URLs in JSF Applications

Posted by Dominik Fri, 05 Jan 2007 15:51:00 GMT

Is it just me, or is the following behavior annoying others as well?

I’ve been playing around with JSF lately and noticed that the URLs displayed by the browser and the pages shown don’t match.

The minimal setup I used was a page which lists all users and a page which displays the details for an user named, respectively, users/list.jsf and users/details.jsf.

The navigation part of the xml configuration I’m forced to write for that trivial application looks like:

    <navigation-rule>
      <from-page-id>/users/list.jsf</from-page-id>
      <navigation-case>
        <from-outcome>success</from-outcome>
        <to-view-id>/users/details.jsf</to-view-id>
      </navigation-case>      
    </navigation-rule>
    <navigation-rule>
      <from-page-id>/users/details.jsf</from-page-id>
      <navigation-case>
        <from-outcome>success</from-outcome>
        <to-view-id>/users/list.jsf</to-view-id>
      </navigation-case>      
    </navigation-rule>

When I navigate to /users/list.jsf the list page is shown as expected. Once I select an entry I get served the details page. Sounds OK, but the browser is still showing /users/list.jsf as URL. And when I use a link on the details page to go back to the list page, the list page gets displayed again. That is fine as well. But now the browser shows /users/details.jsf as URL.

I’ve tested this with not only list and details, but the whole bunch of CRUD pages for Users, and the behavior is consistent. Consistently wrong.

Am I missing a point here?

Somehow I’m used to having some kind of relation between the URL shown by the browser and the page displayed. As I’m typing this, e. g., the URL shown is typo/admin/content/new and not typo/admin/content (which would have been the overview page). Now I have written and used my part of Java web applications, and often the URL shown by the browser was totally useless, but even that is an better behavior than having the wrong URL shown to you.

And it seems like I’m not doing everything wrong. Just checkout the URLs shown in Figures 4 & 5 of http://www-128.ibm.com/developerworks/java/library/j-jsf2/index.html. The same behavior over again.

And I haven’t even started to talk about the fact that, even if the right URL were shown for the details page, I could not bookmark it, because it carries no information about the user whose details I’m viewing at the moment.

Seems like I’m already spoiled by rails…

Posted in  | Tags , ,  | 2 comments | no trackbacks