Daniel Watrous on Software Engineering

A Collection of Software Problems and Solutions

Posts tagged wicket

Software Engineering

Wicket + Guice including unittests

Last week I spent way too much time integrating Apache Wicket and Google Guice. Yikes! The most difficult part for me was getting the initialization to happen in the right order. A big Thank You to Dan Retzlaff on the Wicket list for helping work through these details.

The details below were applied to a Wicket quickstart project for Wicket 6.0.0.

Design Decisions

It was important to me to keep the application tier separate from web tier. I actually maintain each in a separate repository. I have several motivations for this, such as:

  • Clean separation of concerns. In other words, prevent logic from ending up in my Wicket pages
  • Independent revisions and release cycles between web tier and application tier
  • Easier to divide work between scrum teams

I include the application tier into the Wicket front end as a jar. By the way, this also makes it easy to include my application tier into a Jersey REST interface and other legacy servlets.

It was also important to maintain a mock package for fast unittests. Since the data providers are managed in the application tier, the mock package lives there, further enforcing the separation of concerns.

Implementation Approach

After some experimentation I decided to use the GuiceServlet approach. I started by adding the following maven dependencies to my pom.xml for the Wicket quickstart.

        <dependency>
            <groupId>com.google.inject</groupId>
            <artifactId>guice</artifactId>
            <version>3.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.inject.extensions</groupId>
            <artifactId>guice-servlet</artifactId>
            <version>3.0</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>org.apache.wicket</groupId>
            <artifactId>wicket-guice</artifactId>
            <version>6.7.0</version>
            <type>jar</type>
        </dependency>

My web.xml defines only the GuiceFilter and a listener to initialize the injector when the servlet context is created.

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">
 
	<display-name>guicewickettest</display-name>
 
        <listener>
            <listener-class>com.danielwatrous.myapp.web.MyGuiceServletConfig</listener-class>
        </listener>
 
        <filter>
            <filter-name>guiceFilter</filter-name>
            <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
        </filter>
 
        <filter-mapping>
            <filter-name>guiceFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
</web-app>

As you’ll see, this keeps configuration details in code, rather than XML. The web.xml remains simple. That brings us to the GuiceServletConfig, which is where we initialize the injector.

You may recall that listeners receive event notifications at well defined points in the life cycle of a web application or session. Here’s the MyGuiceServletConfig that’s referenced in web.xml:

package com.danielwatrous.myapp.web;
 
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.GuiceServletContextListener;
import com.danielwatrous.myapp.modules.MongoMyappModule;
 
public class MyGuiceServletConfig extends GuiceServletContextListener {
 
    @Override
    protected Injector getInjector() {
        return Guice.createInjector(new MyappServletModule(), new MongoMyappModule());
    }
 
}

The GuiceServletContextListener implements ServletContextListener, which ends up executing when the application context is created (or destroyed). This way we have the injector available before executing any application code.

Another thing you may notice is that I create the injector with two modules, not just one. The first module is the ServletModule, and I’ll show that to you in a minute. The next module is the application tier module that has been included as a jar in the Wicket application. The single injector available throughout the Wicket application will be able to inject servlet/Wicket related components in addition to application tier components.

Let’s have a closer look at MyappServletModule:

package com.danielwatrous.myapp.web;
 
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.servlet.ServletModule;
import java.util.HashMap;
import java.util.Map;
import org.apache.wicket.protocol.http.IWebApplicationFactory;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.protocol.http.WicketFilter;
 
public class MyappServletModule extends ServletModule {
    @Override
    protected void configureServlets() {
        filter("/*").through(WicketFilter.class, createWicketFilterInitParams());
        bind(WebApplication.class).to(WicketApplication.class);
        bind(WicketFilter.class).to(CustomWicketFilter.class).in(Scopes.SINGLETON);
    }
 
    @Singleton
    private static class CustomWicketFilter extends WicketFilter {
 
        @Inject
        private Provider<WebApplication> webApplicationProvider;
 
        @Override
        protected IWebApplicationFactory getApplicationFactory() {
            return new IWebApplicationFactory() {
                @Override
                public WebApplication createApplication(WicketFilter filter) {
                    return webApplicationProvider.get();
                }
 
                @Override
                public void destroy(WicketFilter filter) {
                }
            };
        }
    }
 
    private Map<String, String> createWicketFilterInitParams() {
        Map<String, String> wicketFilterParams = new HashMap<String, String>();
        wicketFilterParams.put(WicketFilter.FILTER_MAPPING_PARAM, "/*");
        wicketFilterParams.put("applicationClassName", "com.danielwatrous.myapp.web.WicketApplication");
        return wicketFilterParams;
    }
}

You may notice that I added a mechanism to provide WicketFilter with additional parameters. Next I bind my WebApplication and WicketFilter classes to specific implementations. The CustomWicketFilter overrides the typical behavior of the WicketFilter which usually takes a string reference to the WebApplication class. Instead it now uses the injected WebApplication object.

As you’ll see below, this step of injecting the desired WebApplication is critical to enabling unittests, primarily because it allows us to construct the WebApplication with an injector.

package com.danielwatrous.myapp.web;
 
import com.google.inject.Inject;
import com.google.inject.Injector;
import org.apache.wicket.guice.GuiceComponentInjector;
import org.apache.wicket.protocol.http.WebApplication;
 
public class WicketApplication extends WebApplication {    	
    private final Injector injector;
 
    @Inject
    public WicketApplication(Injector injector) {
        this.injector = injector;
    }
 
    @Override
    public Class<HomePage> getHomePage() {
        return HomePage.class;
    }
 
    @Override
    public void init() {
        super.init();
        getComponentInstantiationListeners().add(new GuiceComponentInjector(this, injector));
    }
}

At this point Wicket and Guice are successfully integrated. Let’s have a look at what needs to happen to make the unittests work.

Unittests

The only real change that’s required to make the unittests work is in the setUp function of the unittest. Since the WebApplication above was modified to receive an injector, all we need to do is create an injector and provide it at instantiation.

package com.danielwatrous.myapp;
 
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.danielwatrous.myapp.modules.TestMyappModule;
import com.danielwatrous.myapp.web.HomePage;
import com.danielwatrous.myapp.web.WicketApplication;
import org.apache.wicket.util.tester.WicketTester;
import org.junit.Before;
import org.junit.Test;
 
public class TestHomePage {
 
    private WicketTester tester;
 
    @Before
    public void setUp() {
        Injector injector = Guice.createInjector(new TestMyappModule());
        tester = new WicketTester(new WicketApplication(injector));
    }
 
    @Test
    public void homepageRendersSuccessfully() {
        //start and render the test page
        tester.startPage(HomePage.class);
 
        //assert rendered page class
        tester.assertRenderedPage(HomePage.class);
    }
}

You’ll notice in this case I create an injector that doesn’t include the ServletModule and uses the TestMyappModule. Since the Wicket unittests don’t operate within a full web context I don’t need the ServletModule. Additionally my TestMayappModule makes use of my mock package. This allows the tests to run without access to any external resources. It also keeps the tests very fast!

Wicket Pages

Accessing the injector in your Wicket pages is easy. All you need to do is inject it. Here’s how that looks:

package com.danielwatrous.myapp.web;
 
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.danielwatrous.myapp.domain.QuickLink;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.request.mapper.parameter.PageParameters;
 
public class HomePage extends WebPage {
    private static final long serialVersionUID = 1L;
    @Inject private Injector injector;
 
    public HomePage(final PageParameters parameters) {
	super(parameters);
 
	add(new Label("version", getApplication().getFrameworkSettings().getVersion()));
 
        // TODO Add your page's components here
        QuickLink quickLink = injector.getInstance(QuickLink.class);
	add(new Label("quickLink ", quickLink.buildQuickLink()));
    }
}

Great Combination

After working through the particulars, this implementation feels clean and flexible. Configuration is in the code and benefits from compile time type checking. Unittests are working and fast with very little modification to the traditional Wicket approach, which keeps the application testable.

Resources:

http://apache-wicket.1842946.n4.nabble.com/Wicket-Guice-unittests-td4652853.html
https://gist.github.com/3880246

Software Engineering

Wicket + GAE automatic reload

One disappointment of developing for Wicket and Google App Engine (GAE) is that the automatic monitoring and reloading of modified HTML files didn’t work. It had something to do with the single threaded nature of the GAE platform.

I had found a few previous efforts to make this work, but none of them worked with the current version of Wicket and GAE. I went without it for a while, but restarting the web server after every markup change finally drove me to figure it out.

Working with the project that I setup using my Wicket + GAE tutorial, I added two new files and modified the WicketApplication. Here are the details.

GaeModificationWatcher.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package com.danielwatrous.softwarelicensing.web;
 
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map.Entry;
 
import org.apache.wicket.util.listener.IChangeListener;
import org.apache.wicket.util.time.Duration;
import org.apache.wicket.util.time.Time;
import org.apache.wicket.util.watch.IModifiable;
import org.apache.wicket.util.watch.IModificationWatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
public class GaeModificationWatcher implements IModificationWatcher {
 
	private static final Logger LOG = (Logger) LoggerFactory
			.getLogger(GaeModificationWatcher.class);
 
	ConcurrentHashMap<IModifiable, Set<IChangeListener>> listenersMap = new ConcurrentHashMap<IModifiable, Set<IChangeListener>>();
	Duration pollFrequency;
	Time lastCheckTime;
	Object timeCheckLock = new Object();
 
	public boolean add(IModifiable modifiable, IChangeListener listener) {
		checkResources();
		HashSet<IChangeListener> listenerSet = new HashSet<IChangeListener>();
		Set<IChangeListener> listeners = listenersMap.putIfAbsent(modifiable,
				listenerSet);
		if (listeners != null) {
			return listeners.add(listener);
		} else
			return listenerSet.add(listener);
	}
 
	public IModifiable remove(IModifiable modifiable) {
		if (listenersMap.remove(modifiable) != null) {
			return modifiable;
		} else {
			return null;
		}
	}
 
	public void start(Duration pollFrequency) {
		LOG.debug("Starting watcher");
		synchronized (timeCheckLock) {
			lastCheckTime = Time.now();
			this.pollFrequency = pollFrequency;
		}
	}
 
	public void destroy() {
		// do nothing
	}
 
	public Set<IModifiable> getEntries() {
		return listenersMap.keySet();
	}
 
	public void checkResources() {
		Time now = Time.now();
 
		Time timeCheck;
		synchronized (timeCheckLock) {
			if (lastCheckTime == null) {
				return; // not started
			}
 
			Time nextTimeCheck = lastCheckTime.add(pollFrequency);
			if (nextTimeCheck.after(now)) {
				return; // nothing to do, not ready
			}
 
			// lets go
			timeCheck = this.lastCheckTime;
			this.lastCheckTime = now;
		}
 
		Set<Entry<IModifiable, Set<IChangeListener>>> entrySet = new HashSet<Entry<IModifiable, Set<IChangeListener>>>(
				listenersMap.entrySet());
 
		for (Entry<IModifiable, Set<IChangeListener>> entry : entrySet) {
			if (timeCheck.before(entry.getKey().lastModifiedTime())) {
				LOG.debug("Found modification, notifying listeners of change");
				for (IChangeListener listener : entry.getValue()) {
					listener.onChange();
				}
			}
		}
	}
}

GaeReloadRequestCycleListener.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.danielwatrous.softwarelicensing.web;
 
import org.apache.wicket.Application;
import org.apache.wicket.RuntimeConfigurationType;
import org.apache.wicket.request.cycle.AbstractRequestCycleListener;
import org.apache.wicket.request.cycle.RequestCycle;
 
public class GaeReloadRequestCycleListener extends AbstractRequestCycleListener {
 
	public void onBeginRequest(RequestCycle cycle) {
		if (Application.get().getConfigurationType().equals(RuntimeConfigurationType.DEVELOPMENT)) {
			final GaeModificationWatcher resourceWatcher = (GaeModificationWatcher) Application.get()
					.getResourceSettings().getResourceWatcher(true);
			resourceWatcher.checkResources();
		}	
	}
}

WicketApplication.java

I haven’t provided all the details for this class, but this should show you how to implement it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class WicketApplication extends WebApplication
{    	
	...
 
	/**
	 * @see org.apache.wicket.Application#init()
	 */
	@Override
	public void init()
	{
		super.init();
 
		...
 
		// add your configuration here
		getRequestCycleListeners().add(new GaeReloadRequestCycleListener());
		IModificationWatcher watcher = new GaeModificationWatcher();
		watcher.start(Duration.ONE_SECOND);
		getResourceSettings().setResourceWatcher(watcher);
	}
}

Resources

http://agilewombat.blogspot.com/2010/01/wicket-on-google-app-engine.html
http://apache-wicket.1842946.n4.nabble.com/How-can-I-reload-HTML-in-app-engine-td3005241.html
http://apache-wicket.1842946.n4.nabble.com/Reload-html-in-Wicket-GAE-td4363236.html

Software Engineering

Java, Wicket and Hibernate on EC2 (pre-interview project)

Over the weekend I put together a project as a precursor to an interview. I really like interviews where I have a chance to solve a problem that’s more meaningful than generating a random number efficiently.

The pre-interview question came in the form of a sketch of the application. This worked out great since I suggest always starting with a sketch drawn by hand. Here’s what they wanted:

Choice of technology

The instructions indicated that I could use any technology that I was familiar with, as long as I included the libraries necessary to compile the code. Since I’ve been interested in Wicket lately and wanted to get into the latest version of Hibernate (it’s been a few years), I chose Java, Wicket and Hibernate.

For the development IDE I chose NetBeans due to its native support of Maven. Wicket quickstart projects base their build on a Maven pom.xml.

Development

I started my project using the Wicket quickstart. This makes use of Maven archetypes which require Maven2+. Some development benefits that come along with the quickstart include tests that are verified at each compile of the project. This ensures, at a minimum, that your markup and Java files agree.

I used Mercurial (hg) to create a local repository to manage revision control. Even for small projects revision control is a key element and reduces the risk of big refactorings and other explorations. The hg repository can also be ‘pushed’ to anyone else that wants to collaborate on the project.

In some ways, the story that the revision history tells is as important (maybe more so) than the finished product. The revisions themselves provide valuable insight into the way a developer approaches his work.

Database

For the database I chose HyperSQL (HSQLDB). This is a pure Java database with an in memory mode. Hibernate abstracts the database access and makes it easy to move to a more robust production database at some point in the future. HSQLDB makes development easy since the database is initialized each time I restart the jetty server.

Documentation and collaboration

TRAC is my preferred artifact tracking system for software projects. It integrates directly with Mercurial. It provides roadmap, wiki, timeline and other reporting and collaboration devices. Once I got the project to a stable point, I pushed the repository up to a public location with an integrated TRAC instance.

You can checkout the code or view it online using the URL below:

http://danielwatrous.repositoryhosting.com/hg_public/danielwatrous/favorite-movies

To checkout the code using the URL above just enter this command:

hg clone http://danielwatrous.repositoryhosting.com/hg_public/danielwatrous/favorite-movies favorite-movies

Once you have the code cloned to your local system as shown above, run the commands below to compile and run the application (this requires that you have Maven 2+).

mvn compile
mvn jetty:run

You should now be able to view the application at this URL:

http://localhost:8080

Additional development

Next steps in the development of this application may include additional tests, better encapsulation and refined access mechanisms.

For example, aside from the default tests that are a result of the Wicket quickstart, I haven’t added any additional unittests. If the complexity of the application increased if might be worthwhile to add unittests to the Movie and RatingModel classes.

At some point data access could be encapsulated into a DAO for the Movie class. This might be beneficial if access to Movie objects spread to additional pages and those pages duplicated the code required to access those objects.

Deployment

I’ve been keen to play around with Amazon’s EC2 service for a while. This seemed like a perfect opportunity, so I added EC2 to my Amazon Web Services account and created an instance. I chose 64 bit Amazon Linux. I chose Tomcat as the web server.

I added the Tomcat server running on my EC2 instance to the Maven files, which made it possible to build and deploy in a single step from the command line

mvn tomcat:deploy

As development continues I can redeploy easily using this command

mvn tomcat:redeploy

Resources

Download the source

favorite-movies.zip

The following resources were helpful during the development of this application:

Hibernate

http://stackoverflow.com/questions/3345816/hibernate-projects-and-building-with-maven
http://docs.jboss.org/hibernate/core/4.0/quickstart/en-US/html_single/
http://wicketinaction.com/2009/06/wicketspringhibernate-configuration/

Enum support in Java/Wicket

http://yeswicket.com/index.php?post/2009/09/24/Enums-internationalization-with-Wicket
http://blog.armstrongconsulting.com/?p=163
http://stackoverflow.com/questions/3224244/wicket-resource-string-not-found

Amazon EC2

http://coenraets.org/blog/2011/11/set-up-an-amazon-ec2-instance-with-tomcat-and-mysql-5-minutes-tutorial/
http://www.mkyong.com/maven/how-to-deploy-maven-based-war-file-to-tomcat/

Wicket users list

I also found the wicket users list very helpful, as usual:
http://apache-wicket.1842946.n4.nabble.com/form-processing-for-multiple-objects-td4321129.html
http://apache-wicket.1842946.n4.nabble.com/AJAX-Rating-extension-multiple-on-a-page-td4317346.html
http://apache-wicket.1842946.n4.nabble.com/guestbook-application-with-database-update-td4316943.html

Software Engineering

Software licensing: Wicket pages and panels

My initial perception of wicket panels was that they were like includes. This naturally lends itself to header, footer and style content that will be the same throughout a web application and avoids duplicating code.

It seems wicket panels are more widely used than I first expected. For example, I keep seeing examples of a very lightweight page where panels represent the majority of the content too. This is a more segmented approach than I have seen in the past, and I can see some benefits and drawbacks to it.

Based on other frameworks I would typically structure each page with the following files:

  • header [common]
  • footer [common]
  • page

This would be repeated for additional pages with the header and footer representing the only elements common among all pages. In wicket the design changes by adding a new file

  • header [common]
  • footer [common]
  • page [common]
  • panel

By segmenting the content of the page out into panels, the page frame itself becomes reusable. It also makes it possible to use some clever wicket extensions, like breadcrumbs and tabbed ajax panels. These can save a lot of time in development. Another benefit is that it keeps you in the habit of creating panels for page sub-components, which can increase code reuse and maintainability.

The biggest pitfall I have found so far is that panels rely on state and the URLs are not bookmarkable. I know that’s what wicket is all about, but in terms of search engines and bookmarking pages, this can be a big drawback.

For example, when implementing the documentation pages for the API of the software licensing appication, I made use of the breadcrumb extension and put all the content in panels. I found afterward that based on the way it is implemented, it’s not possible to bookmark a link to a specific API document. The same lack of bookmarkable links exists in the tabbedpanel that I planned to use. Unfortunately this won’t do.

While I may leave the content as a panel, I now see that my implementation needs to be pages so that I can map them to specific URLs.

The alternative would be to make use of the extensions and give up the bookmarkable URLs. However, when I’m working with an API, emailing a support or user list or creating tutorials I frequently link to specific API documentation and I rely on Google to know how to find that documentation when I search for it.

I have sent an email to the wicket user list about the whether the breadcrumb extension can be made to work with bookmarkable URLs, but I didn’t get a response. If anyone responds then I’ll update this post with the solution.

Software Engineering

Software licensing: Jersey framework for REST

I did some investigation into building the RESTful API for the software licensing system using wicket. At first I was encouraged that URL management was so easy (nevermind that really old article I just linked to).

Wicket Not Ideal for RESTful APIs

In the end I decided that wicket was not a good choice for the RESTful API. The crux came in treating HTTP methods differently. In other words, for a given resource URI, I want to do something different for GET, POST, PUT and DELETE. That’s not one of wicket’s strengths, so I moved on.

The first framework I looked at had a really slick look. I know that’s not necessarily an indication of technical superiority, but the simplicity of the homepage made me believe that Restlet would be a good choice. But before making my choice, I looked for references and found this stackoverflow discussion.

Jersey Wins

I had seen Jersey before reading that, but was turned off thinking I had to dive deep into glassfish and other technologies. The stackoverflow discussion convinced me to give Jersey a try and I’m so glad that I did. In about a half an hour I had my initial API calls framed and responding to web calls in Google App Engine.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.danielwatrous.softwarelicensing;
 
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.DELETE;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
 
//The Java class will be hosted at the URI path "/sitelicenses"
@Path("/sitelicenses")
public class SiteLicenses {
 
	@GET
	@Produces("text/plain")
	public String getAllSiteLicenses() {
		// Return some cliched textual content
		return "Hello World GET";
	}
 
	@POST
	@Produces("text/plain")
	public String createNewSiteLicense() {
		return "Hello World POST";
	}
 
	// @PUT
	// @DELETE
}

I followed this extremely concise Jersey + GAE tutorial to get things going. There were more jar files required that are shown there. Otherwise I can’t believe how easy it was to get my RESTful API framed in and working.

TIP:

About a year ago I found a great tool to explore REST and test RESTful services. It’s a Chrome plugin named Simple REST Client. This makes it possible to send requests to a URI using any of the HTTP methods and see the full response, including headers. Here’s a screenshot of my first API response:

Software Engineering

WordPress plugin licensing: Wicket on Google App Engine

For the user interface layer of the licensing system I was interested in using a framework like Wicket. It was a lot of work to setup. The process was made somewhat frustrating by the fact that most of Google’s results are a few years old and deal with older versions.

I did finally get it working and here’s the process. Other articles take the default Google App Engine project and modify it to accommodate wicket. I decided to go the other direction and start with the wicket quickstart. This is the process I followed and links to the resources that I used. Hopefully that makes this post age better. We’ll see 🙂

Add Maven support to Eclipse

Since I wanted to start with the current wicket quickstart, I needed maven. Eclipse doesn’t support maven out of the box, but there’s a great plugin that makes working with Maven projects easy. You can get all the details at http://eclipse.org/m2e/.

Generate a wicket quickstart project

The wicket project provides a rather clever mechanism based on Maven to build a quickstart project based on various release version of wicket. You can access the quickstart configuration tool at http://wicket.apache.org/start/quickstart.html.

What that generates is a Maven command. As long as you have Maven installed on your computer, you should be able to generate a quickstart project based on that command. If they maintain this resource then it should be easy to create a fresh project for any future version of wicket. Here’s what I ran to create the quickstart for the licensing system:

Import into Eclipse and Configure for GAE

Now we need to import this project into eclipse and configure it to work with Google App Engine. If you have already install the Maven to Eclipse plugin above then you should be able to import the project. To do this choose File -> Import. From the import dialog choose Existing Maven Project.

On the next screen you provide the path to the directory where the pom.xml file is and choose Finish. Now you have an eclipse project for your wicket quickstart.

Add Google App Engine libraries

Add the Google App Engine libraries to your project by opening the Java Build Path dialog and choosing from available libraries (this assumes you have eclipse setup for google app engine development).

Update project settings for GAE

The process of updating the projects settings feels a bit clumsy because you have to save some settings before others will take. Begin by opening the project settings (right click on project name in Package Explorer panel of Eclipse). The first thing you need to do is set the war directory under Google -> Web Application.

Save this setting and close the properties window. Next you need to reopen the window and navigate to Google -> App Engine. There you will check the box next to “Use Google App Engine”.

This will have generated a problem, but you might not see it. Open the Problems panel in Eclipse using the menu options Window -> Show -> Problems. In the problems view you will see that there’s an error indicating that the appengine-web.xml file is missing. You need to right click on the error and choose Quick Fix. Eclipse will create the appengine-web.xml file for you.

Now would be a good time to make a small update to the appengine-web.xml to enable session support (something that’s disabled by default on the App Engine platform). This change is very straight forward and the line you need to add to the file is already in there as a comment. Here’s the line you need to add:

<sessions-enabled>true</sessions-enabled>

Copy over properties and jars

Now we need a handful of files copied over to our WEB-INF/lib directory so that the GAE development server can find them. This include the followng jar files:

  • log4j
  • slf4j-api
  • slf4j-log4j
  • wicket-core
  • wicket-util
  • wicket-request

I’ve left off the version details since those may be different when you get around to this, but you can see below how your WEB-INF/lib directory should look.

You might have noticed while editing the appengine-web.xml file above that it expects a logging.properties file in WEB-INF. You can create this file with this single line:


.level = WARNING

Update pom.xml output directory, etc.

The default output location for compiled classes is under the ‘target’ directory. The Google App Engine development environment will look under webapp, so we need to modify the Maven configuration file to indicate the directories where we want the compiled classes to go. This is done by adding a couple of elements to the build element as shown below.


<project ...>
  <build>
    <directory>src/main/webapp/WEB-INF</directory>
    <outputDirectory>src/main/webapp/WEB-INF/classes</outputDirectory>
    ...
  </build>
</project>

Related to the above modification, we need to update the classpaths for builds. This is easily done by opening the project properties and removing the hard coded references to the output directory and making sure the default value is correct. Here’s what that looks like:

While we have the pom.xml file open, let’s make a few other small changes. One will reduce the noise of warnings we get during development. This has to do with the encodings of the files that are copied over during a build cycle.


<project ...>
  <properties>
    ...
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
</project>

Wicketstuff gae-initializer

The final required step is to use the gae-initializer that’s part of the wicketstuff repository. You can view the repository https://github.com/wicketstuff/core.

There are two ways to incorporate this into your project. One is through the Maven configuration file. The other is by including the wicketstuff-gae-initializer-1.5.3.jar directly. In order to make my development environment work correctly I had to include the jar file. You can find the jar files here:

http://repo2.maven.org/maven2/org/wicketstuff/wicketstuff-gae-initializer/1.5.3/

To incorporate the gae-initializer into your pom.xml file, open your pom.xml file and click on the Dependencies tab. You can then Add the dependency with the following details:


<project ...>
  <dependencies>
    <dependency>
      <groupId>org.wicketstuff</groupId>
      <artifactId>wicketstuff-gae-initializer</artifactId>
      <version>YOUR-WICKET-VERSION</version>
    </dependency>
    ...
  </dependencies>
</project>

Here’s what it looks like in Eclipse:

I suppose that alone should be enough, and it might be enough for your deployment to production in Google App Engine, but I found that I also need to add the JAR to my build path as an external JAR. This is how I did that:

I now have a running wicket application in Google App Engine.

Resources

Below are a list of old (and very old) tutorials. I couldn’t get these to work with the current version of wicket and GAE. Still, they may be useful if you encounter problems related to features that I didn’t use or test.
http://www.danwalmsley.com/2009/04/08/apache-wicket-on-google-app-engine-for-java/
http://stronglytypedblog.blogspot.com/2009/04/wicket-on-google-app-engine.html
http://stronglytypedblog.blogspot.com/2009/07/wicket-spring-jdo-on-google-app-engine.html

Documentation for gae-initializer in wicketstuff core repository:
https://github.com/wicketstuff/core/wiki/Google-AppEngine-Initializer

This thread covered some points that might fill in gaps:
http://mail-archives.apache.org/mod_mbox/wicket-users/201003.mbox/%3C1269607382.11633.11.camel@kaffeeserver%3E

This article had some discussion of serialization problems. I think that the gae-initializer that I cover in this article addresses the points in the article below.
http://thoughts.inphina.com/2010/10/20/managing-wicket-serialization-problem-on-google-app-engine/

Complaints about GAE not supporting wicket properly (related to above article):
http://code.google.com/p/googleappengine/issues/detail?id=2500

My most recent thread on the wicket users list working through some of the points in this article:
http://apache-wicket.1842946.n4.nabble.com/Wicket-on-Google-App-Engine-td4259205.html