Qwicket 1.0

Qwicket 1.0 is finally here. Apart from being entirely too busy with work and sick children, I've been anxiously waiting along with everyone else for the 1.3 release to go final. This version features some streamlined build process improvements and a more interesting default UI. You'll likely end up building a new UI but at least there's enough there to work with while your design guys build something more customized. Part of the delay has come from some odd compiling and generation problems in my development environment but I appear to have ironed all those out. If you see something odd, please don't hesitate to let me know and I'll try to iron out any issues as quickly as possible. This release isn't entirely revolutionary but I hope to make some dramatic improvements over the next few months making Qwicket much more robust and to make it easier to base projects off of and track the changes as Qwicket evolves. I'd also like to add maven support and move to ant task and maven archetype based generation as that's a little lighter weight for something that (at least for the moment) you use to generate your project and then move on from.

Hopefully Qwicket will help you explore Wicket and get your projects running more quickly. If you have any requests, please feel free to file an RFE in the tracker.

Gosling update

I have to apologize for going so long without saying much on the subject. We're in that mad rush to the finish line trying to finish up a release while the business types are busily moving that finish line farther and farther back. But enough with the sob stories, eh? Most of my online friends already know this but I've decided to drop development on gosling. I have entirely too many irons in the fire and something has to give and this, unfortunately, one of a number of victims of this downsizing. For anyone interested in taking up this project, I'll happily transfer ownership.

WicketTester and Spring

One thing that's always bugged me about testing my wicket applications is that using WicketTester with a Spring-based Application isn't the most enjoyable process. I have been using Selenium to test my applications and that works sort of OK. Selenium has problems detecting which link I click if there are a lot of similar links and since most links in Wicket encode state/version information, you can also have "link drift" so that even when the link is properly recorded, the versioning information might change in a long running session and then Selenium loses the plot. In addition, Selenium tests aren't so simple to run as part of a Hudson run if you're not running Hudson in a windowed environment. So it's not perfect, but I've used it about as well as I can for a while now. But I really wanted that WicketTester option working for me. So I sat down and figured it out. I'm working with Wicket 1.3 snapshots so you'll need at least beta1 to do it this way. Also, I have some database population code in my application's init to prepopulate certain data elements after initial installation so it complicates the scenario a little but not overly much. Also, I'm using TestNG in this example and a slightly modified/cleaned up version of the testng-spring classes. With that set up out of the way, let's get to some code.

The path to this code was rather frustrating once I sat down to actually figure it out, but the solution turns out to be rather simple. My tests extend AbstractTransactionalSpringContextTests and override two methods:

@Override protected String[] getConfigLocations() { return LOCATIONS; }

@Override protected void prepareTestInstance() throws Exception { inject(); setTransactionManager(transactionManager); }

If you've used spring with either junit or testng, the first method is simple enough. It just lets the test harness know where to find the spring config files. This method is called by the testng classes and all you need to worry about is to properly define that String[] to list your config file(s). In my case, that's

private static final String[] LOCATIONS = { "classpath:applicationContext.xml", "classpath:applicationContext-test.xml" };

The second method, I'll admit, might be a set up issue with my environment, but I had no TransactionManager defined so none of my tests would start a transaction which obviously caused a few problems. That transactionManager field is injected by the testng-spring infrastructure from the same TM used by my application at runtime.

So then, back to the actual test class. I initialize my tests with this:

@BeforeMethod public void init() { tester = new WicketTester(new TestMyApplication()); }

@Override protected ConfigurableApplicationContext loadContextLocations(String[] locations) throws Exception { ++this.loadCount; XmlWebApplicationContext context = new XmlWebApplicationContext(); context.setConfigLocations(locations); context.refresh(); return context; }

private class TestMyApplication extends MyApplication { @Override public void init() { ServletContext servletContext = getServletContext(); XmlWebApplicationContext context = (XmlWebApplicationContext)applicationContext; servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, context); context.setServletContext(servletContext); super.init(); } }

I create the WicketTester using a subclasses version of my actual Application. Then I override the testng method to create the application context to make sure the actual implementation matches what wicket-spring will be looking for. The default type is ClassPathXmlApplicationContext which isn't quite what I need. Then I subclass my application and override init() to fetch that application context and add it to the MockServletContext that WicketTester creates. Then I super up to my "real" init() and let things proceed from there.

And that's about it. I use the OpenEntityManagerInView from spring which handles all this for me when I run the application in jetty. But lacking that infrastructure under testng/wickettester, I've had to emulate portions of it and that's what you see here. I just got all this together in the last day or two so there are likely some subtleties missing but it's worked so far for me. Please try this out if you're in a similar situation and if you find missing pieces, please do let me know. I'll keep you updated if I find anything. Enjoy.