June 11, 2006

Spring MVC, Open-Session-In-View, and validation errors

I've seen this problem discussed a lot. Here's my take on it, and my solution:

Problem: (taken mostly from a Spring Forum entry)

When valildation fails, you don't want the changes persisted, but unless you do something, hibernate will automatically update the object. Remember, in this scenario the Spring binding process changes the object, and hibernate is watching the object and knows it has been changed. My solution is to clear the hibernate session. In my controller, which extends SimpleFormController I override the processFormSubmission as follows:
    @Override
    protected ModelAndView processFormSubmission(HttpServletRequest request,
            HttpServletResponse response, Object command, BindException errors)
            throws Exception {
        if (errors.hasErrors()) {
            getService().clearSession();
        }
        return super.processFormSubmission(request, response, command, errors);
    }
The getService().clearSession() method just uses a Dao the has a clearSession method that calls getHibernateTemplate().clear()

Posted by jaynes at 09:30 AM | Comments (0) | TrackBack

June 01, 2006

JavaCosign Rewrite

This is an email I sent to the cosign-dicuss@umich.edu email list a while ago. I'm putting it here as an easy reference.

Quick summary:
Medical School Information Systems (MSIS) here at U of Michigan has written it's own version of JavaCosign-1.5. We'd like to figure out how we might join with the official development process, rather than staying out on our own.
-------------------------

As you may have gathered from my recent emails to you and the cosign-discuss group, MSIS has decided to begin using cosign on at least some of our J2EE web apps. Unfortunately, when we looked at the current implementation of JavaCosign we found that the architecture wouldn't work well for our environment. Currently the implementation tightly couples the filter with the connection pool that connects to the Cosignd servers. Each instance of the filter requires it's own pool. There's no way to share the connection pool between different apps that use the filter.

At MSIS we run many web apps per app server, and most of these apps have relatively light traffic. It isn't efficient for each app to have it's own pool.

Given this, Tony Chan (who just recently joined MSIS) and I decided to rework the code to better suit our needs. Frankly, we stepped back, reevaluated the design, and pretty much rewrote it completely. I know it would have been better to work with the cosign team rather than going off on our own, but we just didn't know how to approach the community with plans for a complete rewrite.

So, now we have an alternate version of JavaCosign-1.5. It is functionally equivalent, with one exception, however the configuration file format is different. The one feature we cut out is the dynamic rereading of the config file if it changes. If the community affirms that that feature is necessary, then we'd be willing to look at putting it back in.

This new version is designed around interfaces and modularity. The filter functionality and the connection pooling functionality are completely separate. The pooling implementation is pluggable, as well as the objects that are pooled. We have two pooled objects implemented: the ConnectionList as in the current JavaCosign, and a SingleConnection object that just keeps open one connection at a time. We have not used JAAS, we have removed all singletons and substituted stateless service objects. We think the code is much simpler to understand and easier to work with (but, of course, we would).

Although we have developed this new version on our own, we do, actually, want to work with the Cosign community. We just aren't sure how to do that. So, how do you suggest we proceed from here?

Will

Posted by jaynes at 08:29 AM | Comments (1)

April 25, 2006

Spring 2.0 - XML Configuration on more steroids

Note: This is my first blog, so there are still formatting issues I haven't figured out yet.

When I saw Memestorm's blog posting on XML configuration on steroids I had to learn more. Read his entry before continuing, as I don't really explain a lot. I'm just showing code. Also, I just figured this out by delving into the Spring code and some of the tags that are available in Spring 2.0. I've got something working, but I'm pretty sure that there are better ways to do what I've done. Hopefully someone will see this blog and tell how I should have done it.

Memestorm's entry was enough to get you started, showing how to create a simple tag. I needed something with embedded tags. I wanted to turn something that, in a traditional Spring config file, looks pretty ugly:

into something that looks like this

It's just a list of service objects, each with a list of pattern objects, each pattern object having two properties, pattern, a string, and allowPublicAccess, a boolean.

XML Schema

So, first, I needed to come up with the XML Schema:

The schema describes the three tags I need, "urlPatten" nested within "service" nested within "services".

Namespace Handler

As Memestorm says, Spring invokes a namespace handler to read your custom XML, and you have to write that handler. Here is what I came up with:

The constructor registers a bean definition parser for the top element, service. The other elements are parsed as part of the code. This is how I saw the Spring code handling nested elements.

The biggest kludge I had to pull, and the part I understand least, has to do with the ListBean class. In the CosignNamespaceHandler the getBeanClass method needs to return the class of the bean that will hold the services element, when it is completely built. That class needs to be instantiated, and properties set in it in the doParse method. But a List is not a bean, and doesn't have properties. After creating the List I didn't know what to do with it. So I created a ListBean that implements List, has a property internalList, and delegates all List methods to this internalList. Then, as the last line in doParse I could call the builder.addPropertyValue method and set the list I had build into a bean. I'm sure there must be some other way to handle this, but I don't know what it is.

Packaging

When you package this all up into a jar, there are two extra files you need to add to the META-INF directory. The spring.schemas file maps the namespace location to the location of the schema file in the jar:

http\://www.umich.edu/schema/cosign/cosign.xsd=edu/umich/auth/cosign/tag/cosign.xsd

The spring.handlers file maps the schema namespace to the namespace handler class:

http\://www.umich.edu/schema/cosign=edu.umich.auth.cosign.tag.CosignNamespaceHandler

And the final thing is, in the Spring bean configuration XML file, use the XML Schema version rather than the DTD version, and map your new namespace to a URI:

Notice the chain that all these names form: xmlns:cosign="http://www.umich.edu/schema/cosign" specifies the URI for the namespace. In the xsi:schemaLocation part of the header, the namespace URI is mapped to a location URI, http://www.umich.edu/schema/cosign/cosign.xsd. This location URI, is mapped to a physical location by the spring.schemas file.

Posted by jaynes at 10:31 AM | Comments (1) | TrackBack