Thursday, April 9, 2009

Wicket on Google App Engine

Google App Engine now supports Java. Let's get Wicket running on it, quickly.

Note: This post covers the basics of setting up Wicket on GAE. This subsequent post takes the next steps of setting up Spring and persistence with JDO and provides the source code of a sample application.

1. Use the Eclipse plugin to create a project
The Eclipse plugin can be installed via Eclipse Update Manager and it includes a Google App Engine SDK, so you don't need to install that separately. With the plugin, create a "New Web Application Project".


Uncheck "Use Google Web Toolkit" and leave "Use Google App Engine" activated. The project will contain a src folder and war folder. It contains a simple "Hello, World" example and you can run it immediately. But let's get Wicket running, quickly.



2. Add Wicket jars
Add the following jars to the war/WEB-INF/lib directory and add them as external jars to the eclipse project:

- wicket-1.3.5.jar
- slf4j-api-1.5.2.jar
- slf4j-log4j12-1.4.2.jar
- log4j-1.2.13.jar



3. Turn on logging
Turn on logging, so that you can see any strange things, that may occur. App Engine won't tell you much by default.

- log4j.properties: log4j.logger.org.apache.wicket=DEBUG, A1
- java6 logging.properties: .level = INFO

4. Create a Wicket Application and a Page
Add WicketApplication.java

package wicket;

public class WicketApplication extends WebApplication {
public Class getHomePage() {
return HomePage.class;
}
}

and a simple HomePage.java and HomePage.html:

public class HomePage extends WebPage {
public HomePage() {
add(new Label("label", new Model("Hello, World")));
}
}



5. Set up WicketFilter
Add the Wicket servlet filter to web.xml. Alternatively use WicketServlet:


WicketFilter
org.apache.wicket.protocol.http.WicketFilter

applicationClassName
wicket.WicketApplication




WicketFilter
/wicket/*




6. Add HTTP session support
Enable HTTP session support (by default it's disabled) by adding the following line to appengine-web.xml:

true


Now the app is ready to run, but there are still some issues.

7. Disable resource modification watching
When Wicket is started in development mode now, exceptions are raised because Wicket spawns threads to check resource files such as HTML files for modifications. Let's just disable resource modification checking by setting the resource poll frequency in our WicketApplication's init() method to null.

protected void init() {
getResourceSettings().setResourcePollFrequency(null);
}

8. Disable SecondLevelCacheSessionStore
We cannot use the SecondLevelCacheSessionStore in the app engine, which is the default. At least not with a DiskPageStore, because this serializes the pages to the disk. But writing to the disk is not allowed in the app engine. You can use the simple HttpSessionStore implementation instead (this increases HTTP session size), by overriding newSessionStore() in our WicketApplication:

protected ISessionStore newSessionStore() {
//return new SecondLevelCacheSessionStore(this, new DiskPageStore());
return new HttpSessionStore(this);
}


9. Run
From the context menu of the project, call Run As -> Web Application. Open http://localhost:8080/wicket/ in your browser and see the app running.


Download the demo as an eclipse poject.




25 comments:

Miaubiz said...

thank you for this! works great so far.

I used 1.4-rc2, besides the the fact that slf4j is 1.2.14 I also have to add slf4j-api in addition to slf4j-log4j.

Jonas Wiklund said...

7. Disable resource modification watching
I know you have to do this, but have anyone figured out a way to disable resource caching in development without resource modification watching since one have to restart the debugger to se a change in a html page otherways.

kerwin said...

Thanks! Since I run the demo app I immediately tried to use Wicket but keep encountering errors. I give up after 3 hours but thanks to this post at least its running.

Anonymous said...

"Turn on loggin, so that you can see any strange thins, that my occure"

!!!! Write out one hundred times !!!!

Turn on logging, so that you can see any strange things, that may occur

Ha ha

Nick Wiedenbrueck said...

@Anonymous: Man, that's so terrible. Fixed.

lborupj said...

I have a "hack" to reload resources in Wicket on Google App Engine

http://lborupj.blogspot.com/2009/04/wicket-on-google-app-engine.html

Gabriel said...

tHqnk you for this article. I used it as a reference in my article (in french) about the same subject.
http://blog.oxiane.com/2009/04/27/deploiement-dune-application-wicket-sur-google-app-engine/
Then i deploied a test application on gae. It worked, but I had a "little" problem with "Collections.unmodifiableList" - I hd to remove then to be GAE compatible - which is astonising...

Troy Borja said...

Hi,

I am new to Wicket and your demo is a great resource. Would you be kind enough to extend your demo to show how to use Wicket with the Google data store?

Nick Wiedenbrueck said...

@Troy Actually, I'm planning to to do a Wicket/GAE project. But sadly, currently I'm not having that much time working on it. So, it might take some time to see post on this topic.

Stefan Meisner Larsen said...

For those who are playing with the DataStore: It seems that classes that has been "enhanced" by the DataNucleus JPA implementation can't be serialized. This means that you can't put them into the session :-(
Has anyone solved this or can anyone prove me wrong?

Regards,
Stefan

Per Lundholm said...

I tried to upload your example but only get a 404 when I click on the link on the first page. Did you really get this running deployed on GAE or just locally?

Regards,
Per

Oliver Koeth said...

Merged your sample with an existing GAE/J application. Worked without any issues "on the real thing".

Merci!

mfg OK

Nick Wiedenbrueck said...

@Per Lundholm: Actually, I did not deploy the sample application i posted, but I successfully deployed another app.

I had another look at the sample app. It includes an index.html with a wrong link. Try http://yourapp.appspot.com/wicket/ instead. This is where the WicketServlet is located.

Per Lundholm said...

Oh, thanks ... I should have figured that out myself. And the slash on the end is sooo important.

Nick Wiedenbrueck said...

The resource modification watching will be fixed as of Wicket 1.4.0-RC6. The Wicket guys introduced a replaceable IModificationWatcher interface.

https://issues.apache.org/jira/browse/WICKET-2340

bwinfrey said...

8. Disable SecondLevelCacheSessionStore

Is it possible to use memcache instead of session as a replacement to writing to file? If so, do you have any implementation ideas?

Thx, B

Nick Wiedenbrueck said...

@bwinfrey: Sounds like a nice idea. Haven't tried yet, though.

Lukáš Zapletal said...

Nice but why do you log via LOG4J when Wicket uses SLF4J and GAE JUL? Its better to use slf4j-jdk14.

Christopher said...

I have an application running quite well on GAE using wicket + spring.

Unfortunately i'm having SERIOUS performance problems (3 seconds per request). Has anyone else developed a GAE+wicket app that is in use and performant?

Alexander Elsholz said...

i've the same performance problems - more than 3 secound per request (ajax). i tried in deployment and development mode - same problem. doeas anyone solved this problem?

Sam Barnum said...

Be sure you don't have the wicket-jmx jar in your app, it will fail with an error:
java.lang.NoClassDefFoundError: java.lang.management.ManagementFactory is a restricted class. Please see the Google App Engine developer's guide for more details.

SN said...

I am still looking for a Big table based PageStore, I know Disk based page store isnt going to work, and
I dont want to keep every thing in session.

b said...

i had to add serialVersionUID to my wicket pages since they are stored in the session and serialized. I guess they are not required by Eclipse when I create a wicket page. before i did that, i was receiving an exception like:

javax.servlet.ServletException: java.lang.RuntimeException: java.io.InvalidClassException: wicket.LoginPage; local class incompatible: stream classdesc serialVersionUID

Anonymous said...

With wicket 1.5 use on application init getStoreSettings().setAsynchronous(false); or you will run into modifythreadgroup problem.

Daniel said...

I have been getting an INTERNAL_SERVER_ERROR for my wicket page but I'm not getting any logging to give more details. On point #3 above, I understood that I should add the details you show to the filename that comes before the colon. Did you mean that I should put those somewhere in the project properties?