Wicket, Spring, Hibernate, Testing... Yeah, it's like that.

Posted by Berin Loritsch Tue, 10 Nov 2009 16:57:00 GMT

I have to deliver a product using Java. Due to politics and approved baselines, etc. I can’t use Ruby on Rails. I’ve done my own thing in the past, and so this time I decided to save some time by incorporating Wicket, Spring, and Hibernate using auto-wiring, and attributes. Getting it all to talk together took the better part of a day, but I got it to deploy and run fine.

I’m an avid unit tester, so I was happy to learn that Wicket has some facilities to make testing a bit easier without forcing you to create your own Servlet mock objects. I was really happy about that, so I decided to try it out. Unfortunately, I ran into a rather nasty roadblock. Spring was complaining about the ContextLoaderListener not being loaded. It’s defined in my web.xml file, but the autowiring requires the spring context to be loaded in a particular location. Finding out how to fix that problem took me the better part of half a day.

The problem is that Wicket hides the ServletContext object away from you. You can’t add values, because the test framework is initialized on construction. Attempts to obtain the ServletContext and manually add the Spring web application context just weren’t working. That’s because it is configured when the WicketTester object is constructed and ignored after that. I needed to be able to inject my own ServletContext with the Spring integration taken care of. I finally figured it out here, because the forums just working for me. Please note that this is tested with Wicket 1.4 and not any of the earlier versions:

final MyApplication app = new MyApplication();
tester = new WicketTester(app) {
    @Override
    public ServletContext newServletContext(final String path) {
        // web context
        ServletContext context = new MockServletContext(app, path);
        // spring context
        XmlWebApplicationContext spring = new XmlWebApplicationContext();
        spring.setServletContext(context);
        // configure spring
        spring.setConfigLocation("classpath:application.xml");

        // put spring where Wicket can find it
        context.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, spring);
        return context;
    }
};

So let me explain what I did. I created an anonymous subclass of the WicketTester class so I could override the factory method “newServletContext” to inject my spring configuration. Done properly, the wicket folks can take care of this by providing a SpringWicketTester subclass in their spring integration library. The SpringWicketTester would let you specify the location of your Spring configuration file, and it would override that method for you. For now, you’ll have to do it yourself.

I put the WicketTester initialization in a subclass of the JUnit TestCase class. That way I don’t have to repeat myself for setting up my Wicket testing.