JRebel Tutorial: Using JRebel with Apache Wicket

The following gives a brief overview of JRebel’s supported integration with the Apache Wicket framework, one of the most widely-used component-based web UI frameworks in the JEE world.

1. Wicket development with JRebel

JRebel together with its plugin for explicit Wicket support takes you to the point where you can do most of your development without redeploying. Let’s take a look at a simple example. Imagine you start out with a trivial web-app with a couple of pages, and deploy it to your application server. One of the pages looks like the following:


HelloWorldPage.java
public class HelloWorldPage extends WebPage {
  public HelloWorldPage() {
    add(new Label("label", "Hello world!"));
  }
}

HelloWorldPage.html
<p wicket:id="label" />

Assume the other page was defined in class AnotherPage. Let’s try adding a new link from the HelloWorldPage to the AnotherPage page. We need to change HelloWorldPage.java and HelloWorldPage.html in the following way:


HelloWorldPage.java
public class HelloWorldPage extends WebPage {
  public HelloWorldPage() {
    add(new Label("label", "Hello world!"));
    add(new BookmarkablePageLink("anotherPageLink", AnotherPage.class));
  }
}

HelloWorldPage.html
<p wicket:id="label" />
<a href="#" wicket:id="anotherPageLink" />

What happens is that JRebel hot-loads the changes made to our HelloWorldPage.class. When we hit “refresh” in the browser, a new instance of the HelloWorldPage is created, meaning that the constructor code is re-executed and the changes take effect instantly. Our JRebel-Wicket plugin also enabled HTML template reloading by default, so Wicket knows to look for HTML-file updates and takes care of that part. Putting it all together, after pressing F5, our new Link component appears in the page. No redeploying, no restarting, no waiting.

The assumption here of course is that our IDE automatically compiles the modified Java code into a folder that JRebel is monitoring, and also that the changed HTML file is copied into that folder. That folder is specified in our rebel.xml configuration file.

2. The JRebel-Wicket integration plugin

JRebel core by itself just takes care of the reloading of classes part. Let’s also have a quick look on the issues our JRebel-Wicket plugin is explicitly dealing with to extend the support for Wicket development without redeploying. The JRebel-Wicket plugin is distributed inside the jrebel.jar and enabled by default. You can explicitly force it to be disabled or enabled by starting your appserver with the additional JVM parameter -Drebel.wicket_plugin=false (or true, correspondingly).

2.1. Reloading of HTML templates

Supported for versions: Wicket 1.2.x, 1.3.x, 1.4.x.

Of course, as Wicket is about creating web UI, the other type of resources besides the Java .class files are the HTML templates. The default behavior of Wicket is to load them once and cache them for the rest of the application’s lifetime, but it also supports a more developer-friendly mode of monitoring the templates’ timestamps and reloading them automatically when required. As we assume that having JRebel set up in the app-server indicates that we are obviously running in a developer’s environment, JRebel will automatically turn on Wicket’s HTML template reloading feature. Notice you could have done so yourself with adding one simple line of configuration to your WebApplication implementation class’s init() method:


protected void init() {
    getResourceSettings().setResourcePollFrequency(Duration.ONE_SECOND);
}

You can also override the value set by JRebel-Wicket plugin by setting it to something else in the init() method.

2.2. Injecting dependencies with @SpringBean annotations

Supported for versions: Wicket 1.3.x, 1.4.x.

A popular configuration is to use Wicket together with the Spring framework, using Spring as a dependency injection container. When Wicket creates new instances of your various Page subclasses, the Wicket-Spring integration would then take care that the Spring-managed service beans (e.g. DAOs) get injected into the desired instance fields (marked by the @SpringBean annotations in your code). An example of such a Page subclass could look as follows:



public class ClientPage extends WebPage {

  @SpringBean
  private ClientDAO clientDao;

  public ClientPage() {
    Client client = clientDao.getClientById(1);
    add(new Label(...));
    //..
  }
}

When you navigate to the corresponding page in your application, Wicket automatically creates the ClientPage instance (or deserializes an existing one if that seems more appropriate), and Wicket-Spring integration injects the ClientDAO service bean, so basically you don’t have to worry about any of that stuff yourself. JRebel of course doesn’t break any of this existing functionality, plus enables you to instantly reload all the changes that you have made to the ClientPage class without a redeploy. The scenario that doesn’t work out-of-box is the one of adding a new bean reference to your class, for example by editing the previous code in the following way:


  @SpringBean
  private ClientDAO clientDao;

  @SpringBean
  private CompanyDAO companyDao;

  public ClientPage() {
    Client client = clientDao.getClientById(1);
    Company company = companyDao.getCompanyById(1);
    //..
  }


Although JRebel hot-loads the changes, Wicket-Spring has already remembered the fields that it needs to inject each time a new ClientPage instance is created, which would lead to a NullPointerException when calling getCompanyById, as companyDao wasn’t injected. Fortunately, our explicit JRebel-Wicket integration solves this problem by telling Wicket-Spring to empty its caches and rebuild them in such a situation.