I've just recently created a tutorial / starting example on how to get the two working together for some documentation I'm having to put together. Hopefully it will get you going. I used a lot of the information from this thread to get me going, but I had to fill in the missing details.
Oh, and it should be noted that the code provided was written from memory. In other words, I'm dumbing down my working code to make the example easier. So while I'm pretty sure everything is going to work, there might be a few minor hitches along the way for you. The idea is all there though. Feel free to post corrections or updates and I'll try to keep them all updated.
I'll post it in full... now:
GWT and JFreeChart
This article describes how to integrate JFreeChart and GWT. It assumes development is being done in Eclipse. It also assumes that the reader has an understanding on how Remote Procedure Calls (RPCs) are created and accessed in GWT. For more information on this, go to the GWT Developer Guide (apparently I can't have urls in my post since I'm new, so just do a web search and find it) and follow the Remote Procedure Calls link.
The included example will create two services running as servlets. The first service will be a chart generator service that has one function, which generates a standard pie chart with data created on the server. It will store the pie chart as an image and return the name of the image to the GWT caller. The second service will - given the chart name - return the image data, allowing it to be displayed.
Download JFreeChart
Get the latest JFreeChart version. Be sure to get the package that contains the latest JCommon version. Unpack the download, which will leave you with a number of JARs. For the included example, you will only be concerned with `jfreechart-{version}.jar` and `jcommon-{version}.jar`.
Update Project Classpath
Update your project's classpath with references to the two JARs mentioned above.
Create Chart Generator Service
Create a service interface for generating charts. The service will create the chart and store it on the server, so it should return the name of the chart that it generates.
For this example, there will only be one function and it will accept no parameters. All of the data for the chart will be created on the server. In the real world, this function could receive a collection objected containing the dataset the caller wishes to be plotted. It could also allow the caller to pass in chart display properties to affect how the chart is presented, such as dimensions and colors.
Note: It is important to understand how GWT creates RPCs for the following code examples.
Create the interface (client):
- Code: Select all
package com.example.client;
import com.google.gwt.user.client.rpc.RemoteService;
public interface ChartGenerator extends RemoteService {
public String generateChart();
}
Create the asynchronous implementation interface (client):
- Code: Select all
package com.example.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface ChartGeneratorAsync {
public void generateChart(AsyncCallback callback);
}
Create the implementation of the interface (server):
- Code: Select all
package com.example.server;
import javax.servlet.http.HttpSession;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.servlet.ServletUtilities;
import org.jfree.data.general.DefaultPieDataset;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.example.client.ChartGenerator;
public class ChartGeneratorImpl extends RemoteServiceServlet implements ChartGenerator {
public String generateChart() {
/*
* Hold our stored chart name, it will be returned to the GWT caller.
*/
String chartName = "";
/*
* Create the data for this example.
*/
DefaultPieDataset dataset = new DefaultPieDataset();
dataset.setValue("One", 10.0);
dataset.setValue("Two", 50.0);
dataset.setValue("Three", 30.0);
/*
* Generate the generic pie chart.
*/
JFreeChart chart = ChartFactory.createPieChart("New Pie Chart", dataset, false, false, false);
/*
* Save the chart as an '300px x 250px' jpeg image.
*/
try {
HttpSession session = getThreadLocalRequest().getSession();
chartName = ServletUtilities.saveChartAsJPEG(chart, 300, 250, null, session);
} catch(Exception e) {
// handle exception
}
/*
* Finally, return the chart name to the caller.
*/
return chartName;
}
}
Your chart generator service is now complete, all that is needed now is to define the service in the `.gwt.xml` module descriptor.
- Code: Select all
<servlet path='/chartGenerator'
class='com.example.server.ChartGeneratorImpl'/>
Setup Chart Display ServiceJFreeChart provides a servlet for displaying a previously stored chart. All you need to do is call the service, providing the chart name as a parameter. So simply define the service in your module descriptor as follows.
- Code: Select all
<servlet path='/displayChart'
class='org.jfree.chart.servlet.DisplayChart'/>
Making a Call from the ClientNow that the services have been defined, implemented, and deployed, all that is left is to make calls from the client to the services.
For this example, we'll create a new `Widget` called `ChartImage` which will - in its constructor - setup a connection to the chart generator service, make a call to the service to generate a new chart, receive the new chart's name back from the generator service, and finally use the chart display service to add the chart on the client side.
To use the chart display service, you simply need to set your image source to call the service with the proper parameters. For our example, this will look as follows.
- Code: Select all
<img src="./displayChart?filename={chart-name}"/>
Note: It is important to understand how GWT use RPCs for the following code examples.- Code: Select all
package com.example.client;
import com.google.gwt.user.client.ui.Image;
public class ChartImage extends Image {
private ChartGeneratorAsync chartGeneratorService;
public ChartImage() {
super();
/*
* Setup connection to chart generator service.
*/
chartGeneratorService = (ChartGeneratorAsync) GWT.create(ChartGenerator.class);
ServiceDefTarget endpoint = (ServiceDefTarget)chartGeneratorService;
String url = GWT.getModuleBaseURL() + "chartGenerator";
endpoint.setServiceEntryPoint(url);
/*
* Setup the callback from the chart generator service.
*/
AsyncCallback callback = new AsyncCallback() {
/*
* If the call was successful, we will get back the name of the chart
* that was created and stored on the server.
*/
public void onSuccess(Object s) {
String chartName = (String)s;
String imageUrl = "./displayChart?filename=" + chartName;
setUrl(imageUrl);
}
/*
* Something went wrong with the call. Handle the issue how you'd like.
*/
public void onFailure(Throwable ex) {
// do nothing for now
}
};
/*
* Make the call to the chart generator service with the previously created
* callback.
*/
chartGeneratorService.generateChart(callback);
/*
* Since we've made an asynchronous call, we don't need to do anything further.
* The callback object will handle the remainder of the work for us.
*/
}
}
In the example above, the image will not be shown until the callback is run, since we didn't include any initial setup code. We could, for example, choose to start the image with a loading icon, which would change into the chart itself once the asynchronous callback is run.
Deploy Project
And that's it! You can now compile and run your code!
Hopefully this helps you get started down a workable path.