On integrating Spring Security ( formerly Acegi) with a Spring application
Had a tough time as I tried integrating spring security with a simple spring application. It is only beginning to dawn on me now, that Spring is one vast framework. Struts feels like a walk in the park as compared to Spring and all its extra modules. But to be fair, Spring offers much more.
Now I understand that "convention over configuration" is useful only if the developer knows exactly what is going on. This ideology advocates leaving a lot of things unsaid, so if you don't configure everything, lots of components in your system will take on their default values, mostly inspired by the Ruby people. Good for a quick start to your project, but be prepared to go on a google hunt if you want precise control. Isn't it wonderful that now it is possible to have a running application without knowing how half of those things work? Simple example: if you want to use spring security out of the box, then the database tables for user needs to have specific names for all the columns, and the front end form elements need to have exact names like j_id, which is not so well documented. And for the simple default case, all this will work even though you don't know what's going on inside.
Coming to what went wrong today...
First, I added a security-context.xml file to my spring application setup. Now, the spring security authentication manager takes an authentication provider, which in turn needs a user service. I missed those user definitions, and of course I didn't know that.
So, what error message do i get on the server:
SEVERE: Error listenerStart
Nov 5, 2010 7:48:25 PM org.apache.catalina.core.StandardContext start
SEVERE: Context [/stackoverflow] startup failed due to previous errors
Hmm.. something wrong with the logging, no detailed log messages. Need to fix that first.
Two hours later, I stumble upon a blog post that says that Log4jconfigListener internally resets a property webapp.root. (log4jconfigListener is a spring specific listener that looks for a log4j property file in a specified place, and simplifies your logging support.) Also, we learn that Tomcat maintains system wide properties, so each application should keep its own version of this property.
Great, we put in a new context parameter in the web.xml file for this, called webAppRootKey.
Also, the order of listeners in the web.xml can have some consequences. So, the log4jconfigListener needs to come before the other spring listener, contextloaderlistener.
Now the logging was pretty well setup, still saw no log messages.
Another hour later:
Someone posts there on the spring forum:
"I often think about adding little bits of information as I learn more. Then after a while the information seems trivial - obviously since I've learned it and I can no longer remember the key fact that is needed to pass on. However, this is one I have to pass on. Maybe most of you already know this but I;m sure some won't!"
Thank you so much.
I attached the source of the spring jars to the project in eclipse, put a breakpoint in the contextloaderlistener as advised by the post. Now, I deployed the application from the Tomcat manager console. (Configuring the tomcat admin console is definitely useful.) The step return followed by a look in the variables window gave me a simple message:
"You must supply user definitions, either with child elements or a properties file (using the 'properties' attribute)"
which is a very accurate message, it took me about 2 minutes to correct this. Just goes to show that in application development, finding the problem is the hard part that requires skill. Resolving it is often easy.