A fairy tale of the Wicket and the Maven

ApollotempelLately I’ve been working on several Apache Wicket projects. Wicket is quite an intuitive and well-rounded web-application framework. Well intuitive for someone who has been programming Java for a long time. Since for the moment I am back to using Real Java (as opposed to Android), I am also happily back to using Maven and that’s what this article is mostly about.

When starting out with a new technology I think it’s best to jump in and get started on a project. Because nothing teaches as fast as doing and nothing leaves the same lasting impressions as the mistakes you make.

The fastest way to introduce yourself to wicket is the Wicket Quickstart project. Here’s the commandline (you could also do the same by creating a project in Eclipse but I would have to provide screenshots and much more explanation, when the original page – see link above – does the same quite well).

Say hello to Wicket

mvn archetype:generate -DarchetypeGroupId=org.apache.wicket -DarchetypeArtifactId=wicket-archetype-quickstart -DarchetypeVersion=1.5-RC5.1 -DgroupId=com.workreloaded.wicket -DartifactId=profiles -DarchetypeRepository=https://repository.apache.org/ -DinteractiveMode=false

So now you have this fresh new wicket project. You programmed a few counters, a form and integrated a bit of Hibernate. You used some of the shiny Ajax features. Maybe you even downloaded the ebook Version of Wicket in Action and started on your own version of the Cheesr example. You have probably encountered Models and found some documentation and examples. You have fiddled around with CSS layouts for a while. You have run your application countless times with the integrated Jetty server by just running the provided Start class (now isn’t that neat?). You have decided it’s time to tackle something bigger: a real project. One of those ideas you always wanted to …

The Demonstration Paradox

It’s a bit later. You have done it. You have finished a first version of your idea, a prototype. You want to show the world your greatness and what you have programmed these last few days (or weeks). You want to deploy! You install Tomcat or Jetty on your server and just like that everything works out right from the start – it’s like a fairy tale (or this would be a different article on “how to configure an application server”).

So you copy your nice new mygreatidea-0.0.1-SNAPSHOT.war to the webapps folder of your application server. You even gathered a crowd of soon-to-be-impressed friends, followers and circles. Excitedly you click on the link to the app to present it: http://mydomain.com:8080/mygreatidea/. “Lo and behold my …” but wait, didn’t you forget something? You forgot the magic Wand of Making All Installation Locations The Same and now it’s too late: the demonstration paradox is staring back at you and whoever is looking and beholding.

I wonder which of the classics hit first: no styles, no database or is it only the debug mode or is your application just slow because of the huge amount of logging your writing out? (Note: there’s a place in the persistence.xml that calms down Hibernate – a lot!)

Since this is a fairy tale we can easily travel back in time and correct those mistakes. But what were the mistakes? There was basically just one mistake that every developer makes more than once (this particular mistake seems to have some difficulty leaving enough of an impression for us to learn from even if the results can by quite catastrophic): It is the “But it works on my computer!” effect. Corollary: “But it works on my computer and the development system!”

Not all installation locations are created equal, some are for example more restrictive than others. Because this problem exists everywhere, every self-respecting build tool offers a solution. The solution that Maven provides is called “profiles”. You may have used them but have you introduced them from scratch to a project? It’s quite simple actually, most of the work is done in the pom.xml.

Prolific Profiles

First you get to add this little snippet to your pom.xml or your parent-pom or even your .m2/settings.xml.

[sourcecode language=”xml” wraplines=”true”]
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<build.profile.id>dev</build.profile.id>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<build.profile.id>prod</build.profile.id>
</properties>
<activation>
<property>
<name>profile</name>
<value>prod</value>
</property>
</activation>
</profile>
</profiles>
[/sourcecode]

This creates 2 profiles, a development profile and a production profile. You can have as many different profiles as you want. For now each profile has a single property: an id that can be used elsewhere in the build. Also important is the activation tag: it determines when this profile is going to be used. In this snippet we have two variants: automatic activation for the default profile and activation by a property: mvn clean install -Dprofile=prod. There are even more types of activation for example you could automatically select the production profile when you want to create a release (I’ll leave this to you to find out as a small exercise).

Next you need to collect the profile specific information. Typical examples for profile specific information can include but are not necessarily limited to:

  • database configuration
  • logging configuration
  • debug modes
  • path information
  • different implementations in your code

I am sure you can think of some more. So to allow you to control all these different configurations it would be wise to have a central property file that collects all those differences between your different deployments. Let’s see what the file config.properties could look like for the development profile:

[sourcecode]
database.name=mygreatidea
database.user=me
database.password=mypassword
logging.level=DEBUG
logging.path=mygreatidea/log
wicket.mode=development
[/sourcecode]

For other profiles you would have the same properties but of course different values. You need to place the different properties in files in such a way that maven can find them by the profile id that we defined in the first xml-snippet. Most commonly this is done in profile specific directories:

mygreatidea\profiles\dev\config.properties
mygreatidea\profiles\prod\config.properties

Now you must make this information known to the build. This is again done in the pom.xml by simply adding a so-called filter to the build.

[sourcecode language=”xml”]
<build>
<filters>
<filter>profiles/${build.profile.id}/config.properties</filter>
</filters>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
<resource>
<filtering>true</filtering>
<directory>src/main/webapp</directory>
</resource>
</resources>
</build>
[/sourcecode]

What this does is quite simple: it will apply this filter to all files for which filtering is true. Applying the filter means quite simply substituting any properties (don’t worry I’ll get to that) found in the files in src/main/resources (and src/main/webapp) with the profile specific properties from the config.properties file. In a typical Wicket project you will find both the log4j.properties and the persistence.xml in that resources folder hierarchy. Adding something as resource also causes Maven to copy those files to the target folder.

In Wicket projects the files in src/main/webapp are not normally filtered because the war plugin is by (Wicket) default configured to look for them in the src folder. However the easiest way to deactivate development mode in wicket is by adding the information to the web.xml config file. So I have added webapps as resources to be copied to the target folder. (You will also have to modify the Start class, that you use for local testing. It also needs the filtered files, just point it to target instead of src/ and you’ll be fine.)

In the final step add this to your web.xml

[sourcecode language=”xml” highlight=”3″]
<context-param>
<param-name>configuration</param-name>
<param-value>${wicket.mode}</param-value>
</context-param>
[/sourcecode]

There are two important things to note in this snippet: first it shows how to turn on or off development mode in Wicket (allowed values are development or deployment by the way). Secondly and most importantly it demonstrates how the properties in your profile can be used in the filtered files. It should now be easy to add your properties to the logging configuration and your database configuration.

You can even use this mechanism to generate profile specific java code (of course that is a bit more complicated unless you only substitute string literals).

After you finished replacing all the profile specific values with properties during your timetravel in the past, you go back to the future just to the point before the deployment and you dazzle the crowd with your great idea™

I think profiles are a very important addition to any project because you only have to think about each difference once, implement it and forget about it. And if you do encounter the demonstration paradox it’s quite easy to not repeat the same mistake because there’s simple way to fix such problems!

Thanks for reading. I hope you enjoyed this little tale. It’s the week-end and I am entitled to have some fun 🙂

This entry was posted in development, java. Bookmark the permalink.

Comments are closed.