Sunday, January 8, 2012

Updates to Scala/Spring/Hibernate/Maven Webapp

One of the projects I maintain is a public domain code base on GitHub called Scala-Spring-Hibernate-Maven-Webapp. The repository contains source code for kickstarting your own webapp project using the latest versions of Scala, Spring Web, Hibernate and Maven.

Project Updates
I've been committing some major changes over the last couple of weeks, including:
  • Upgrading to Scala 2.9.1, Spring 3.1.0 and Hibernate 4.0.0 
  • Adding to the existing REST-ful Create and Retrive examples some Update and Delete operations 
  • Adding server-side form validation using JSR-303 annotations with Spring Web MVC 
  • Creating examples of automated web testing using Selenium WebDriver and the PageObjects pattern
 If you're about to start your own project with these technologies, or are just keen to see how they all work together, you can get your own copy of the source code from here:
https://github.com/GrahamLea/scala-spring-hibernate-maven-webapp

Resolved Issues
I encountered a couple of time-consuming issues during the upgrades to the latest versions and I think it would be worth sharing how they were resolved in order to save some time for others googling for solutions to the same problems.

Spring Schema SAXParseException
After upgrading the versions of all the Spring Schemas in my Spring XML files, I started getting the following error while trying to start up the webapp:
org.xml.sax.SAXParseException: cos-all-limited.1.2: An ''all'' model group must appear in a particle with '{'min occurs'}'='{'max occurs'}'=1, and that particle must be part of a pair which constitutes the '{'content type'}' of a complex type definition.
At first this appears to be a bug in the Spring schema, but a bit more investigation revealed that it is, in fact, a bug in an old version of the Xerces XML parser library. In my case, an old version of the library was being pulled in through commons-dbcp. The solution I took was to explicitly add a dependency on the latest version of Xerces:
        <dependency>
            <groupId>xerces</groupId>
            <artifactId>xercesImpl</artifactId>
            <version>2.9.1</version>
            <scope>runtime</scope>
        </dependency>

Hibernate Function Not Supported
After upgrading Hibernate to 4.0.0, I started getting this error message whenever I tried to execute a query:
org.hibernate.exception.GenericJDBCException: This function is not supported
Caused by: java.sql.SQLException: This function is not supported
I don't remember whether HSQLDB appeared in the stack trace or not, but the solution to this was to upgrade the version of HSQLDB I was using from 1.8.0.10 to 2.2.6. If you get the same error and you're not using HSQLDB, I would suggest considering an upgrade of your JDBC driver or maybe even your database server.

"No Session found for current thread" 
Also after upgrading to Spring 3.1.0 and Hibernate 4.0.0, and after changing all my Hibernate 3 Spring beans to the corresponding Hibernate 4 versions, I started getting the old classic "No Session found for current thread" error when trying to view any page with a transaction. I thought this was very odd, because the traditional solution to this has always been to make sure you have an OpenSessionInViewInterceptor, but I already had one, defined like this:
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
        <property name="interceptors">
            <list><ref bean="openSessionInViewInterceptor"/></list>
        </property>
    </bean>
By pure chance, I'd seen a Spring documentation page earlier the same day where I'd noticed an alternative way of declaring interceptors using the 'mvc' namespace:
    <mvc:interceptors>
        <ref bean="openSessionInViewInterceptor"/>
    </mvc:interceptors\>
Replacing my old DefaultAnnotationHandlerMapping definition with the one above got my OpenSessionInViewInterceptor working again and solved the "No Session found for current thread".

No Appenders for Log4J
Finally, this one is a bit silly, but I spent a good half hour on it without finding any good help on the web so I thought it was worth documenting. At some point I started getting this error out of Log4J every time I started my webapp:
log4j:WARN No appenders could be found for logger
After all kinds of googling, experiments with winding back dependency upgrades and investigations into ClassLoaders, I eventually noticed that I just had a typo in the Log4J configuration file:
og4j.rootCategory=INFO,Console
Notice the 'l' missing at the start of that line? Ouch. So if you're getting this error message about no appenders and you think your log4j config is all set up properly, check whether the config for your root category is correct before investing too much time in breakpoints inside Log4J classes.

Want to learn more?
Here's some books you might find useful if you plan to go further with Spring, Hibernate, Scala or Maven:
From Amazon








From The Book Depository

Spring in Action - Craig Walls & Ryan Breidenbach (Manning)

Hibernate in Action - Gavin King & Christian Bauer (Manning)

Spring Recipes - Gary Mak (Apress)

Programming in Scala - Martin Odersky, Lex Spoon & Bill Venners (Artima)

Maven - A Developer's Notebook - Vincent Massol & Timothy M. O'Brien (O'Reilly)

1 comment: