Finally, you can use KavaChart imaging
beans to add graphical output to your own servlets
or server-side output. The com.ve.kavachart.servlet package includes a
collection of imaging beans
that can be used by your servlets or JSP output to create dynamic graph
images. Each
subclass of com.ve.kavachart.servlet.Bean includes support for multiple image
types, server-side
caching, and definable client-side imagemaps. Bean properties are
identical to those used
by the com.ve.kavachart.applet collection for rapid prototyping and
experimentation.
For complete KavaChart ProServe details, please see
The KavaChart ProServe User's Guide
To increase the compatibility between servlets and applets, KavaChart servlets use exactly the same property/parameter strings (and parameter parsing class) as KavaChart applets. This makes it easy to switch from applet to servlet and back. For example, this is a simple applet definition that creates a bar chart:
<applet code="com.ve.kavachart.applet.barApp" width=300 height=200> <param name="dataset0yValues" value="321, 234, 234, 456> <param name="xAxisLabels" value="apples, oranges, peaches, pears"> </applet>The same JSP tag definition looks like this:
<chart:streamed chartType="com.ve.kavachart.servlet.barApp"> <chart:param name="dataset0yValues" value=321, 234, 234, 456 \> <chart:param name="xAxisLabels" value="apples, oranges, peaches, pears" \> </chart:streamed>Because server objects run on the server, rather than the client, the chart and image computation expense isn't automatically distributed across many machines. In fact, the server may be called upon to generate many charts simultaneously. To maximize KavaChart's servlet production speed, the com.ve.kavachart.servlet package implements a mechanism to cache images on the server. Once a particular chart definition has passed through the servlet to generate an image file, subsequent requests can simply retrieve the requested image from the server's cache, rather than generate it dynamically.
ProServe deployment varies somewhat from server to server, but for most servers, you can get started by simply placing the "kavachart.war" file into your web applications directory (usually "webapps"). This will create a sample KavaChart installation with JSP chart tag samples and JSP scriptlet samples.
To generate an image, KavaChart employs various classes in Java's AWT package. These classes require certain Java features that may not be available by default on Unix based servers. To access these features in a Java installation of 1.4.0 or greater, you can accomplish this by setting the java property java.awt.headless = true. This can be done by passing the argument "-Djava.awt.headless=true" to your JRE on startup. To use KavaChart with a Unix server and an older version of Java, please consult the Appendixes in The KavaChart ProServe User's Guide.
application.getRealPath(String)method for obtaining the proper name of your cache directory.
Java Server Pages (JSP) give you a high level of abstaction to separate
content from presentation. JSPs inherit all the multi-platform,
multi-threading,
object oriented heritage of Java. KavaChart ProServe objects are easy to
use from within a JSP. The best way to combine KavaChart with your JSP is to use our custom
tag library. You can find examples
using the tag library in the kavachart.war file
as well as a tutorial
describing how to use these tags. Here's a sample: KavaChart tags will help you to
separate your presentation and business logic layers, making your JSPs
simple and easy to maintain. They also implement the best
optimization
logic to make your chart generation as fast as possible. The
chart tag
DataProvider class also helps you re-use your existing data sources for
chart generation. If you still prefer to use scriptlets, though, KavaChart ProServe
objects make the task easy. Here's a simple example JSP that
creates a chart object, generates some data using a Java scriptlet, and generates
chart output:
A few things are worth noting in the sample above. First, the ProServe object is
imported and
instantiated. Then a set of properties describe the chart, and a list
of
random numbers is provided as chart data. Finally, the chart is
generated
when the chart filename is requested. Since we didn't provide a fixed
file
name, the chart uses a name derived from the chart properties.
The chart is written into a specified directory, which we know (the
code assumes, anyway) is the same as our "application root" plus
"cache". The chart is referenced in the
outgoing HTML stream so it will be easy to add additional text and
graphics.
If we wanted to stream the bytes out instead, we'd need to set the
"content type"
and get the image bytes from our chart.
KavaChart ProServe,
JSP and taglib
<chart:streamed dataProviderID="myData" style="myStyle" />
<%@ page import = "com.ve.kavachart.servlet.barApp" %>
<jsp:useBean id="chart" class="com.ve.kavachart.servlet.barApp" scope="page"/>
<html>
<head><title>Simple Chart Generation</title></head>
<body bgcolor="white">
<font size=4>
<%
//add some random data here:
StringBuffer sb = new StringBuffer();
double d = Math.random();
sb.append(d);
for(int i=0;i<5;i++){
sb.append(",");
d = Math.random();
sb.append(d);
}
chart.setProperty("dataset0yValues", sb.toString());
//set a few other properties to make the chart look nice
chart.setProperty("titleString", "hello, world");
chart.setProperty("writeDirectory", application.getRealPath("/cache"));
chart.setProperty("yAxisOptions", "gridOn, minTickOn");
chart.setProperty("xAxisOptions", "gridOn");
chart.setProperty("plotAreaColor", "lightGray");
chart.setProperty("dwellUseXValue", "false");
chart.setProperty("dwellYString", "value: XX");
//now attempt to get a background color from a Request parameter:
String s = request.getParameter("bc");
if(s!=null){
chart.setProperty("backgroundColor", s);
}
%>
<p>
here's the chart:
<img src=/cache/<%= chart.getFileName() %>>
<p>
And here's the same chart with tooltips:
<%= chart.getLinkMap() %>
<img src=/cache/<%= chart.getFileName() %> BORDER=0 ISMAP USEMAP=#map0>
</body>
</html>
Property | value type | effect |
chartType | String | the kind of chart you want to generate. These are all the "App" files in the servlet package, and include all the chart types enumerated in the Individual Charts section of the documentation, such as "barApp", "lineApp", and so on. The default chart type is a horizontal bar chart. If you want to reference a chart that's not in the com.ve.kavachart.servlet package, it must be a subclass of com.ve.kavachart.servlet.Bean, and you must provide the fully qualified name (e.g. "chartType=com.ve.kavachart.contrib.TwinAxisDateLineServlet"). This parameter is for "ChartServlet" only, and doesn't apply to individual server beans. |
imageType | String | Output image type. This defaults to a pure Java png encoder. Available imageTypes are j_png (for png images, recommended), svg (for scalable vector graphics), swf or flash (for a flash image), jpeg (using Sun's native JPEG encoder), j_jpeg (using a java jpeg generator), j_bmp (a java .BMP file generator), and gifencoder |
properties | string | a server-side properties file containing default chart properties. This is a great way to set up a customized look for your chart without constantly passing the same parameters to the servlet. This parameter is only used by ChartServlet, if you are using a Bean subclass then use the loadProperties(String s) method instead. |
height | integer | pixel height of generated image |
width | integer | pixel width of generated image |
writeDirectory | String | KavaChart writes image files into this directory. By default this is set to "public_html/images". Since writeDirectory is "public_html/images" by default, the server will attempt to write images into $SERVER_ROOT/public_html/images/file_name. You can also specify an absolute path, such as /usr/lib/webserver/images for this directory. The write directory must be writable by the servlet engine, and readable by the web server. NOTE: this property is currently disabled in ChartServlet for security reasons. |
readDirectory | String | This is the cache directory browsers will use to retrieve images generated by ChartServlet. By default, readDirectory is "images", which means the servlet will return an "img src" tag that points to "images/filename.jpg". See also "writeDirectory". This property isn't used by general ProServe objects, but only by ChartServlet. NOTE: this property is currently disabled in ChartServlet for security reasons. |
debug | String | If a KavaChart servlet finds the parameter "debug" it will log messages to the server log about files names, locations, sizes, etc. The value of this parameter is ignored. |
useCache | boolean | If "true", the servlets will attempt to use an image in the cache directory matching this servlet's parameters. If "false" the image will be generated each time. Note: if you are reading data by reference (e.g. dataset0yURL) and the data changes from time to time, you should either use this parameter to generate a fresh image, or clear the image cache whenever your data changes. Image caching is enabled by default. If useCache is false and byteStream is true, the bean won't write any output to the server's disk. NOTE: this property is currently disabled in ChartServlet for security reasons. |
byteStream | boolean | By default, the servlets write an image to disk, and then send a <IMG SRC=...> message to the response OutputStream. If byteStream is set to "true", however, the servlet will instead set the content-type to the appropriate image type and send a stream of bytes. Note, however, that servlet parameters must still be set to generate a meaningful chart. By combining useCache=false and byteStream=true you can avoid using the server's disk entirely. NOTE: this property is currently disabled in ChartServlet for security reasons. |
fileName | String | An image file name for this servlet. By default, the servlets use a Secure Hash Algorithm (SHA) to create a digest of all the parameters in a given servlet definition. This digest is used to create a filename that uniquely identifies a chart defined by a given set of parameters. The servlet's CacheManager looks for the unique SHA filename in the image cache, and sends that image without regenerating it, if the image exists. Any change in the parameters, even the addition of an unused parameter, will create a new file name, and will cause the image to be regenerated. You can override the default image name with this parameter to force the image to be a specified name NOTE: this property is currently disabled in ChartServlet for security reasons. |
mapName | String | ToolTips and hyperlinks use client side imagemaps to link strings and URLs to image geometries. These imagemaps must be named. The default name is "map0". This property lets you override the map name. |
toolTips | true/false | Tells the ChartServlet whether to create a client-side MAP for tool-tip dwell labels. |
hasLinkMap | true/false | Tells ChartServlet whether to create a client-side MAP for hyperlinks (set using DatasetNLinks). The default value is true |
internalData | true/false | If "internalData" is set to true, KavaChart beans will look for data from the method getDataset(ChartInterface,int). This method gives you an alternate way of retrieving data that might provide better performance or cleaner code than property lists. |
antialiasOn | true/false | Turns antialiasing on for the resulting chart image. Antialiasing requires a java 2 environment (jdk 1.2 or above) |
compressOutput | true/false | This determines whether svg output will be compressed or not. This defaults to true. |
useCacheCleaner | true/false | Determines whether an instance of CacheCleaner will be created to clean up the cache directory. |
cacheCleanerDirectory | String | This sets the cache directory to be regulated by CacheCleaner. Note that CacheCleaner cannot tell the difference between chart images and other files so it will delete any files in this directory over the expiration age. |
cacheCleanerInterval | integer | Determines the sleep interval in minutes for this instance of the CacheCleaner |
cacheCleanerExpirationTime | integer | Any file in the cache directory over this age in minutes will be automatically deleted by CacheCleaner |
First, it's important to note that KavaChart servlets are in a Java package. Unlike simple demonstration servlets, KavaChart servlets require a number of interdependent Java classes, and are organized into package groupings. Your servlet engine probably has a "HelloWorld" class that would run from a browser something like this:
http://server:8080/servlet/HelloWorldYou would replace "server" with the name of your server machine or with localhost if the server is on your local machine. Similarly, you'd replace "8080" with a different port, if your servlet engine uses another port, and "servlet" might be different on your configuration. If "HelloWorld" were part of a package called "demo", you'd start it from your browser like this:
http://server:8080/servlet/demo.HelloWorldThe equivalent command for the sample KavaChart servlet would be similar to this:
http://server:8080/servlet/com.ve.kavachart.servlet.ChartServletWhen the server receives this HTTP GET command, it will attempt to find a Java class named ChartServlet.class in the com.ve.kavachart.servlet package located within it's CLASSPATH. Next, it will attempt to create a JPEG image in the directory "public_html/images", since we didn't change the default writeDirectory within our command. The servlet will return something like <IMG SRC="images/abcd123.jpg">. Your browser will then attempt to get this image file with a conventional HTTP transaction.
We could modify our servlet URL a little bit to write the image to a specific location, and just return the image stream instead of an IMG SRC tag. We'll also add a "debug" parameter to add some information on the server console or log about the image name. Finally, we'll add a parameter to define a bit of data. Here's our modified URL:
http://server:8080/servlet/com.ve.kavachart.servlet.ChartServlet?byteStream=true&debug=true&writeDirectory=/usr/tmp&dataset0yValues=123,342,123You can also refer to your servlet with a registered name. Consult your server documentation for information on how to do this. A registered name can be the same or different than the actual class name. Some servers also permit you to create servlet aliases that will automatically create shortcuts to servlets (and startup properties in some cases).
Another common technique is to use Server Side Include (SSI) to pre-process HTML output to embed the output of a servlet. Pages that contain servlet definitions usually have a .shtml or .jhtml suffix to notify the server that the page should be filtered for servlet output before being sent to a browser. This is what an SSI definition might look like:
<servlet code=com.ve.kavachart.servlet.ChartServlet>ColdFusion servers use the CFSERVLET tag instead of SERVLET, but use the same sort of server-side include syntax. However, if you're a ColdFusion MX user, the tag library is a much cleaner way to implement KavaChart with your data sources. See The KavaChart ProServe User Guide for more information.
<param name="chartType" value="barApp">
<param name="dataset0yValues" value="321, 234, 234, 456">
<param name="xAxisLabels" value="apples, oranges, peaches, pears">
</servlet>
In our first approach, we'll use a KavaChart imaging bean to build an image on the server. Ignore the details for the moment, we'll explain how servlets work shortly. Focus instead on the overall approach. Here's the code:
public class SimpleChartServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
ServletOutputStream out = response.getOutputStream();
com.ve.kavachart.servlet.Bean chart = new com.ve.kavachart.servlet.barApp();
chart.setProperty("imageType", "j_png");
chart.setProperty("useCache", "false");
chart.setProperty("byteStream", "true");
chart.setProperty("xAxisLabels", "Larry, Curly, Moe, Bob, Dave");
chart.setProperty("dataset0yValues", "123,432,123,543,345");
chart.setProperty("width", (new Integer(WIDTH)).toString());
chart.setProperty("height", (new Integer(HEIGHT)).toString());
response.setContentType("image/png");
out.write(chart.getImageBytes());
}
}
This code simply creates a charting bean, sets some string pairs as
bean properties, and retrieves an image name. Compared with using
KavaChart Enterprise Edition's core charting classes,
there are several advantages to this approach, as well as some minor
disadvantages:
First, you don't need to learn the com.ve.kavachart.chart API to use these
beans. Simply follow the examples in our
applet HTML, or use the applets to experiment with various properties.
Second, you can isolate the chart aesthetics
into a properties file that is external to your application. Third,
you'll have automatic access to a variety
of image output types, and a server-side cache management mechanism.
Finally, the properties code is completely
portable among chart types. It doesn't hurt, for example, to set a pie
chart starting angle if you're using a
bar chart. It's also
worth noting that the KavaChart objects are in use at thousands of
installations, and have gone through extensive testing and optimization.
On the other side of the ledger, the beans are a "black box" image generation engine. If you run into problems, they may be more difficult to solve than if the code is all in your servlet.
If you plan to build an image generation servlet, you should also look into the
KavaChart "DataProvider" interface, which makes your data sources portable across
a variety of techniques, and lets you populate a chart with data directly, rather
than with property strings. You can read about DataProviders in the
KavaChart ProServe User's Guide
and in the Tag Library Tutorial
Here is a list of public Bean methods that
will help you make the most of KavaChart in your
servlets, JSPs, and ASPs:
Imaging Bean API
Method | Effect |
Constructor(java.util.Properties) | any bean subclass can be instantiated with a java.util.Properties to provide predefined charting properties. The properties available are all those listed for applets and servlets. |
public void generate() | Generates an image file or ByteArray based on the current property settings. |
public String getFileName() | Retrieves the user specified fileName or the default file name. If the image for this chart has not yet been generated, calls generate(). |
public byte[] getImageBytes() | Retrieves this image as an array of bytes. Generates the image if required. Retrieves the bytes from image cache if available. |
public String getParameter(String) | Retrieves a property, or parameter, if set. |
public Enumeration getParameterNames() | Retrieves the current list of available properties. |
public String getProperty(String) | see getParameter(String). |
public void setProperty(String, String) | Sets a specified property to a specified value. Consult the list of servlet properties, general properties, and chart-specific properties for more information. |
public void setProperties(Properties props) | Sets
the properties for this charting bean. It's often more efficient
to read your properties one time, and let this object persist in your
servlet or application memory, rather than create a new Properties
object for each chart. |
public void accumulateProperty(String, String) | Some properties take the form "a,b,c,d". For example, the property "dataset0yValues" might look like this: "432,123,432". In a servlet, ASP or JSP, it's often easier to accumulate these properties in a loop that examines a resultset from a database lookup. To create the list for dataset0yValues, you'd call this method three times: accumulateProperty("dataset0yValues", "432"), accumulateProperty("dataset0yValues", "123"), and so on. Consult the list of servlet properties, general properties, and chart-specific properties for more information. |
public String getLinkMap() | Retrieves HTML statements for a client-side imagemap that contains tool-tip information for each Datum (based on the dwellLabel properties above) and a set of hyperlinks (based on the datasetNLinks and datasetNTargets properties above). This string contains the geometries for each data item on the chart (pie slice, bar, line vertex, etc.) and may be quite large for complex charts. |
public void loadProperties(String) | Loads properties from a specified include file. This file contains a single column of entries with the form "propertyName=value". |
public ChartInterface getChart() | Retrieves the internal com.ve.kavachart.chart.Chart object from the charting bean for direct customization in java code. |
public Dataset getDataset(ChartInterface c, int index) | Method for you to override to provide one data series in com.ve.kavachart.chart.Dataset form. |
public void setUserImagingCodec(UserImagingCodec codec) | Adds a custom class to be used by Bean to produce the output file or bytestream. This can be used to encode charts to postscript files, transparent gif files or other file types not supported by CacheManager. Any custom class should extend com.ve.kavachart.servlet.UserImagingCodec and override either the public byte[] drawChartToOutputStream(ChartInterface), or public byte[] encodeImageBytes(Image) methods. Two such sample classes can be found in the contrib package, they are com.ve.kavachart.contrib.PostScriptEncoder, and com.ve.kavachart.contrib.GifEncoderForKava. |
Active Server Pages (ASP) can also be used for generating dynamic content from Microsoft web servers. Unfortunately, Microsoft has chosen to drop support for Java in newer installations of ASP, but if you have a Java-enabled version of IIS, KavaChart ProServe bjects can be installed as COM objects for use with any ASP scripting mechanism, such as VisualBasic, JScript, and so on. Here's how:
Use the "jar" command to extract the
kcServlet.jar file into the appropriate directory:
Now you're ready to create an ASP that uses a KavaChart object.
Below is a sample ASP that generates chart
output this way:
In this example, we instantiate our COM object by calling
Server.getObject,
and then set properties that describe what the chart should look like.
We
could use a link to a database or some other dynamic data mechanism to
populate our chart data, but to keep things simple, we just put a
static
set of numbers into the chart.
When we call the getFileName method, the chart generates its output
data
(PNG encoded, per our request) into a file in the specified
writeDirectory.
Since we didn't specify a file name, the chart object creates one based
on this charts unique properties. Subsequent requests for an identical
chart
will use that file rather than regenerating it.
Even though our example uses JScript, you're free to use VisualBasic
or
some other scripting language you're familiar with to populate the
chart
properties. The high level of abstraction lets you create the chart in
the most convenient way possible, while the more difficult charting and
image
generation code disappears from your code base. You'll find both JScript and VBScript examples in the "asp"
directory.
<%@ LANGUAGE = JScript %>
<html dir=ltr>
// Create an instance of the BarChart object
chart = Server.getObject("java:com.ve.kavachart.servlet.barApp.class");
//Use your instance of the BarChart object
//write into the server tutorial directory - where this ASP file should go...
chart.setProperty("writeDirectory", "/winnt/help/iishelp/iis/htm/tutorial");
//use png output
chart.setProperty("imageType", "j_png");
//set a size
chart.setProperty("width", "500");
chart.setProperty("height", "300");
//some values
chart.setProperty("dataset0yValues", "123,432,123,432,123");
//some aesthetics
chart.setProperty("dataset0Color", "green");
chart.setProperty("backgroundColor", "aabbff");
chart.setProperty("3D", true);
chart.setProperty("yAxisOptions", "gridOn");
chart.setProperty("titleString", "KavaChart is Cool!");
chart.setProperty("subTitleString", "with a little Java...");
chart.setProperty("XDepth", "3");
chart.setProperty("YDepth", "3");
str = chart.getFileName();
%>
<h3></A>The automatically generated filename is <%= str%>.</h3>
<img src=<%= str%>>
</FONT>
</BODY>
</HTML>