Wednesday, June 12, 2013

Wicked Charts 1.5.0 released

Wicked Charts has been released in version 1.5.0.

Wicked Charts is a Java Wrapper for the popular Highcharts JavaScript charting library. It provides ready-made Chart components for JSF2.1, Apache Wicket 1.4.x, 1.5.x and 6.x.

New Features in Version 1.5.0 include the support for Wicket 1.4.x and Highcharts 3.

See http://www.wicked-charts.org for details.

Monday, May 13, 2013

Wicket 101 - Changing the location of your HTML markup

This post applies to Wicket 6. 


Most components in Wicket consist of a Java class and a corresponding HTML markup file. By default, Wicket looks for the HTML markup for a component directly next to it in the Java classpath. For most cases, this is a reasonable configuration. However, for the few cases in which you want Wicket to look for the HTML markup files in another location, here is how.

Add the following line to the init()-method of your Application class:

getResourceSettings().getResourceFinders()
  .add(new WebApplicationPath(getServletContext(), "/"));

The result is that you can put your HTML files directly in the web archive path(in a Maven project this would be src/main/webapp) instead of into the classpath. If you use a Path instead of a WebApplicationPath, you could also put your files somewhere on the filesystem of the server. Also, you can implement your own IResourceFinder.

Wednesday, May 1, 2013

Managing Multiple Eclipse-Workspaces with Shortcuts

Most of us are working on more than one project at once, each living in its own eclipse workspace. Eclipse supports this with the workspace feature and even provides a function to switch between workspaces. A not so commonly known function of eclipse is that it also supports command line arguments which make life a little easier if you have multiple workspaces. This way, you can create multiple shortcuts on your desktop, each starting the same eclipse installation with a different workspace. How to do this in an orderly fashion is described in the following.

Create ECLIPSE_HOME system property

First, create the system property ECLIPSE_HOME, pointing to the folder in which you have your eclipse version of choice installed. If you need more that one eclipse installation, simply create multiple system properties with different names. You can also skip this step completely but it makes the shortcuts we create later more robust.


Create JAVA_HOME system property

The JAVA_HOME system property should already be set on most systems. However, you should check that it points to a JDK and not to a JRE.

Create a shortcut for each workspace

Now, create a shortcut for each of your workspaces that you want to quick access for. In windows, create a .bat file in each workspace folder with the following content (in unix systems this can be created analogous):
"%ECLIPSE_HOME%\eclipse.exe" -vm "%JAVA_HOME%\bin" -data .
This shortcut will start the eclipse installed in ECLIPSE_HOME with the Java runtime lying in JAVA_HOME. Eclipse will start with the current folder (".") as workspace.

Conclusion

Having a quick access shortcut to each workspace like above saves some time switching between workspaces. You can play around with the eclipse command line parameters and add some more or change them. More command line parameters of eclipse can be found here.

Saturday, April 6, 2013

Batch Formatting of Java Source Files with Eclipse

Sometimes it is helpful to format a whole batch of Java source files in the same style your eclipse source formatter is configured. This is for example very helpful if you have to merge two development branches and you want to format the source files of both branches before comparing them to remove unimportant differences between both branches.

The eclipse source formatter has a hidden feature that allows it to be run on a directory of java files with a simple shell command:

eclipse -application org.eclipse.jdt.core.JavaCodeFormatter -verbose -config <PATH_TO_CONFIG_FILE> <PATH_TO_JAVA_SOURCES>

Parameters:

  • <PATH_TO_CONFIG_FILE>: Path to the properties file containing the configuration of the code formatter. This file is created in .settings/org.eclipse.jdt.core.prefs when you configure the formatter in eclipse for a specific project
  • <PATH_TO_JAVA_SOURCES>: Path to the folder containing the java source files to format.

Sunday, March 31, 2013

Advanced Wicket: Dynamic ListView within a Form

With ListView, Wicket provides a nice and easy way to create dynamic lists with no problem to add, remove or shift items during runtime. When using a ListView to list input fields in a form however, things can get strange...here's a solution.

The Requirement

You want to create a form that contains multiple input fields. The user shall be able to add input fields or remove previously added  input fields.

Problem #1

By default the ListItems within a ListView are removed, newly created and added back to the ListView each time the ListView is rendered. If you add a new ListItem with a new input fields to the ListView, the user input in these fields will be lost when the page is re-rendered.

Solution #1

A solution to this problem is quickly found: just call listView.setReuseItems(true). This tells the ListView not to create new ListItems each time it is rendered. However, this leads to Problem #2.

Problem #2

Each ListView is backed by a model that contains a list of items that are to be displayed. If a new item is added to this list and setReuseItems is set to true, the ListView will wrap only this new item in a new ListItem and add the ListItem to the ListView the before it is rendered the next time (see ListView.onPopulate()). Since ListView works on the index of the backing model list, each time you insert a new item in the middle of this list, ListView will think you added it at the last position of the list. The result ist that each time you add a new item to the model list (no matter where you put it), the last item of the list is added to the ListView. When the ListView is rendered this can lead to duplicated rendering of the last item.

Solution # 2

Always (!) add items at the end of the model list that backs a ListView. This way, ListView will add the correct ListItem before being rendered again. If the new item is to be displayed in the middle of the list, override the ListView's renderIterator() method. Here you can create an iterator that sorts the items according to their model values. Here is an example from my Wicked Forms library:
@Override
protected Iterator<Component> renderIterator() {
 return iterator(new Comparator<Component>() {
  @Override
  @SuppressWarnings("unchecked")
  public int compare(Component o1, Component o2) {
   ListItem<Abstractformelementmodel> item1 = (ListItem<Abstractformelementmodel>) o1;
   AbstractFormElementModel model1 = item1.getModelObject();
   ListItem<Abstractformelementmodel> item2 = (ListItem<Abstractformelementmodel>) o2;
   AbstractFormElementModel model2 = item2.getModelObject();
   return model1.getIndex().compareTo(model2.getIndex());
  }
 });
};

Wicked Forms - Dynamic Forms Library

Before building your own dynamic form have a look at Wicked Forms. With Wicked Forms you can "describe" your form in plain java and let Wicket render it without having to hassle with details as described above. 

Monday, January 7, 2013

Rolling your own AJAX Behavior with Wicket

Apache Wicket provides a lot of predefined AJAX components like the AjaxButton and the AjaxEventBehavior which fulfill almost any of your AJAX-needs. However, in some special cases you may need to create your own AJAX behavior to pass some custom parameters from client to server via AJAX.

The Problem

The AJAX Behaviors Wicket provides all have a specialized function. The AjaxButton provides an onSubmit-Method to react on a form submission via AJAX. The more general AjaxBehavior provides an onEvent-Method in which you can update parts of your page via AJAX.

But what to do if you have some client-side javascript logic that makes some calculations and you want to send the result of that calculation to your server via AJAX? The following sections provide a surprisingly simple solution for this problem. Scroll to the bottom to see the full 30 lines of the finished behavior class if you want to skip the tutorial part :).

The Behavior

First, we have to create our own AjaxBehavior by subclassing AbstractDefaultAjaxBehavior. The respond-method has to be implemented. This method is called on the server-side when an AJAX call is made from the client. In this method, we want to somehow access some values that are passed from the client-side.
public class MyAjaxBehavior extends AbstractDefaultAjaxBehavior {

  @Override
  protected void respond(AjaxRequestTarget target) {
    // here, we want to access some parameters that were sent 
    // by the client via AJAX
  }
 
}

Calling the Behavior from Client-Side Javascript

The behavior does nothing so far. It has to be called from the client-side for the respond-method to be called on the server-side. To achieve this, we simply implement the renderHead() to execute some javascript when the page is loaded (you can also add this javascript to any other event of course, like clicking a button).

public class MyAjaxBehavior extends AbstractDefaultAjaxBehavior {

  @Override
  protected void respond(AjaxRequestTarget target) {
    // here, we want to access some parameters that were sent 
    // by the client via AJAX
  }

  @Override
    public void renderHead(Component component, IHeaderResponse response) {
    super.renderHead(component, response);
    response.render(OnDomReadyHeaderItem.forScript(getCallbackScript()));
  }
 
}

Remember to call super.renderHead(). Otherwise Wicket's javascript files will not be included. The AbstractDefaultAjaxBehavior class already provides a method that generates the javascript that is needed to issue an AJAX request: getCallbackScript(). This method will generate a javascript fragment something like the following, where "u" and "c" are two Wicket-specific parameters that are needed to find our AjaxBehavior on the server side an call its respond()-method.

Wicket.Ajax.ajax({"u":"./?1-1.IBehaviorListener.2-component","c":"component"});

Passing Parameters from Client to Server

Let's say we have two custom parameters, param1 and param2, that we want to pass from the client-side javascript to our server-side code. How to do that?

Wicket provides the concept of "extra parameters" that can be added to the javascript AJAX call by adding the "ep" parameter to the function call:

Wicket.Ajax.ajax({
  "u":"./?1-1.IBehaviorListener.2-component",
  "c":"component",
  "ep":[
    {"name":"param1","value":"value1"},
    {"name":"param2","value":"value2"}]});
The Strings "value1" and "value2" will then be submitted via the AJAX call. Our Behavior will have to be altered to generate the extra parameters in it's javascript output. We do this by overriding the method updateAjaxAttributes():


public class MyAjaxBehavior extends AbstractDefaultAjaxBehavior {

  @Override
  protected void respond(AjaxRequestTarget target) {
    // here, we want to access some parameters that were sent 
    // by the client via AJAX
  }

  @Override
  public void renderHead(Component component, IHeaderResponse response) {
    super.renderHead(component, response);
    response.render(OnDomReadyHeaderItem.forScript(getCallbackScript()));
  }

  @Override
  protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
    super.updateAjaxAttributes(attributes);
    attributes.getExtraParameters().put("param1", "value1");
    attributes.getExtraParameters().put("param2", "value2");
  }
 
}


However, our Ajax call will now always pass the values "value1" and "value2" for our two parameters. What we want is to pass values dynamically calculated in javascript.

Passing Dynamic Parameter Values 

To pass dynamically calculated javascript values to the server, these values have to be calculated first, and then added into our "extra parameters" array.

To dynamically calculate the parameter values, our renderHead-method is altered. Remember: if you want to trigger the AJAX event somewhere else and not onDomReady, you can do so. For the calculation of the javascript values you can call any Javascript module you might use.

  @Override
  public void renderHead(Component component, IHeaderResponse response) {
    super.renderHead(component, response);
    String script = "var param1Value = My.JavaScript.Module.calculate1();";
    script += "var param2Value = My.JavaScript.Module.calculate2();"; 
    script += getCallbackScript();
    response.render(OnDomReadyHeaderItem.forScript(script));
  }


Next, we have to pass the javascript variables param1Value and param2Value as "extra parameters" in our Wicket.Ajax.ajax function call instead of the fixed values "value1" and "value2". This can be done by overriding getCallbackScript() and slightly altering our implementation of updateAjaxAttributes() from above:


@Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
  super.updateAjaxAttributes(attributes);
  attributes.getExtraParameters().put("param1", "PLACEHOLDER1");
  attributes.getExtraParameters().put("param2", "PLACEHOLDER2");
}

public CharSequence getCallbackScript() {
  String script = super.getCallbackScript().toString();
  script = script.replace("\"PLACEHOLDER1\"", "param1Value");
  script = script.replace("\"PLACEHOLDER2\"", "param2Value");
  return script;
}
 
The method updateAjaxAttributes() now inserts placeholders into the extra parameters map. The method getCallbackScript() is overridden to replace all occurrences of these placeholders within quotes with the names of the javascript variables that contain outr calculated values.

The workaround with the placeholders is neccessary because otherwise we will have extra quotes around our javascript variable names (i.e. the value of param1 will always be the string "param1Value" instead of the actual value of the javascript variable with that name).

Accessing the passed Parameters on the Server

At last, we can access the values of the javascript variables on the server within the respond() method of our behavior:
@Override
public CharSequence getCallbackScript() {
  RequestCycle cycle = RequestCycle.get();
  WebRequest webRequest = (WebRequest) cycle.getRequest();
  StringValue param1 = webRequest.getQueryParameters().getParameterValue("param1");
  StringValue param2 = webRequest.getQueryParameters().getParameterValue("param2");
  // do whatever you need with param1 and param2
}

The Complete Behavior

Finally, the whole behavior at a glance:

public class MyAjaxBehavior extends AbstractDefaultAjaxBehavior {

  @Override
  protected void respond(AjaxRequestTarget target) {
    RequestCycle cycle = RequestCycle.get();
    WebRequest webRequest = (WebRequest) cycle.getRequest();
    StringValue param1 = webRequest.getQueryParameters().getParameterValue("param1");      
    StringValue param2 = webRequest.getQueryParameters().getParameterValue("param2");
    // do whatever you need with param1 and param2
  }

  @Override
  public CharSequence getCallbackScript() {
    String script = super.getCallbackScript().toString();
    script = script.replace("\"PLACEHOLDER1\"", "param1Value");
    script = script.replace("\"PLACEHOLDER2\"", "param2Value");
    return script;
  }

  @Override
  protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
    super.updateAjaxAttributes(attributes);
    attributes.getExtraParameters().put("param1", "PLACEHOLDER1");
    attributes.getExtraParameters().put("param2", "PLACEHOLDER2");
  }

  @Override
  public void renderHead(Component component, IHeaderResponse response) {
    super.renderHead(component, response);
    String script = "var param1Value = My.JavaScript.Module.calculate1();";
    script += "var param2Value = My.JavaScript.Module.calculate2();";
    script += getCallbackScript();
    response.render(OnDomReadyHeaderItem.forScript(script));
  }

}

Sunday, September 2, 2012

Deploying a Wicket App on Google's AppEngine

Google's App Engine (GAE) cloud infrastructure provides a fast and easy way to deploy a Java web application to the public web. And it's free up to a certain traffic threshold. So, I tried it with a Wicket application and had to overcome some small obstacles. Following is a description of the steps necessary to deploy a Java application (precisely, a Wicket application) to Google App Engine.

Create a GAE account

Go to https://developers.google.com/appengine and create an App Engine account. If you already have a Google Mail account, it's just a click.

Install GAE SDK

Download the GAE SDK for Java here. Unzip it anywhere on your hard drive.

Prepare your Java application for GAE

Next to the standard web.xml deployment descriptor you need to provide a descriptor called appengine-web.xml in the WEB-INF folder of your WAR. Following is the content of an appengine-web.xml with which I successfully deployed a demo app on App Engine:
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <application>wicket-charts</application>
  <!-- Version must only contain letters, hyphens ("-") and numbers! Otherwise, 
  a HTTP 500 will occur on update -->
  <version>1-2-0</version>

  <threadsafe>false</threadsafe>

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

  <system-properties></system-properties>
</appengine-web-app>

Take care that the content of the version tag contains only letters, numbers or hyphens (no periods!). Otherwise you get an inexpressive HTTP 500 error when deploying the application.

Additionally to providing a depoyment descriptor you have to adhere to some restrictions GAE imposes on java applications. The main restrictions are:

  • Your application may not store anything in the local filesystem (which actually already is a constraint of the servlet API, but most application servers do not enforce this rule)
  • Your application may not use all classes of the JRE. For example, AWT/Swing classes are a no-go for GAE applications. The classes you may use are listed in a white list.

The second restriction is by far the more constraining. You simply cannot run an application on GAE that uses one of the prohibited classes! This makes the deployment of applications built without GAE in mind a gamble.

Prepare your Wicket application for GAE

The steps above are valid for all Java applications. For making a Wicket application ready for GAE, simply put the Google App Engine Initializer in the classpath of your application and you're done. The initializer will automatically configure your Wicket application on startup so that it adheres to the GAE restrictions. Among other things, the initializer configures your application not to use Wicket's DiskDataStore which stores the PageMap in the file system.

If you want to have full control over how your Wicket application is configured, you have to make the necessary configurations in your application's init method yourself (but you have to find out yourself what configurations are necessary for the application to run on GAE).

Deploy your application on the GAE development server

To test if your application runs on GAE, run the following command:
<path_to_appengine_sdk>/bin/dev_appserver.cmd <path_to_your_war>
where <path_to_your_war> points to a directory (expanded war archive) and not a war file.

On http://localhost:8080 you should now see your application.

Deploy your application into the GAE cloud

To finally deploy your application to the cloud, run the following command:

<path_to_appengine_sdk>/bin/appcfg.cmd update <path_to_your_war>

where <path_to_your_war> again points to a directory. You will be prompted to enter your GAE login credentials before the application will be uploaded.

You should then be able to access your application on http://<your_app_id>.appspot.com.