Bringing SVG Power to Java Applications

   
   

Articles Index


More and more often these days, desktop and web applications need to display and interact with rich graphics. The Scalable Vector Graphics (SVG) format published as a World Wide Web Consortium (W3C) Recommendation in September 2001 is part of the response to that need. SVG allows you to describe two-dimensional graphics -- such as generic shapes, images, and text -- with an eXtensible Markup Language (XML) grammar. These graphics can be styled through Cascading Style Sheets (CSS) or XML, using advanced styling functionalities such as color gradients and filter effects. SVG is the W3C-recommended, XML-based, standards-based alternative to similar proprietary formats.

This article will demonstrate how to build SVG libraries and applications on top of the Java platform. I use the example of the ILOG JViews Component Suite (a Java 2D and Swing-based two-dimensional graphics library) for building visually rich user interfaces. You'll see how a Java SVG-enabled library lets you interoperate with many third-party applications -- from SVG authoring tools to SVG user agents.

After a short introduction to SVG and the ILOG JViews Component Suite, we'll follow the building path of a typical SVG application deployed on the Internet. Finally, we'll take a look at future SVG possibilities, such as deployment on resource-limited devices.

SVG and ILOG JViews Component Suite in a Nutshell

As mentioned previously, SVG is a web format that allows content developers to create two-dimensional graphics in a standard way, using an XML grammar. Several artist authoring tools (such as Adobe Illustrator and Corel Draw) already support this format. To get a better idea of how SVG works, take a look at the following simple example:

<svg width="640" height="240">
  <title>SVG Hello World! Example</title>
  <defs>
       <linearGradient id="the_gradient" 
         gradientUnits="objectBoundingBox" 
         x1="0" y1="0" 
         x2="1" y2="0">
           <stop offset="0" stop-color="rgb(204,204,255)"/>
           <stop offset="0.2" stop-color="rgb(204,204,255)"/>
           <stop offset="1" stop-color="rgb(102,102,204)"/>
       </linearGradient>
  </defs>
  <g>
       <rect x="0" y="0" width="640" height="480" fill="url(#the_gradient)"/>
       <text x="145" y="140" transform="translate(175,140) scale(4) skewX(30) 
       translate(-175,-140)" font-size="24" font-family="ComicSansMS"          
       fill="rgb(255,255,102)">Hello World!</text>
  </g>
</svg>

The code would be rendered like this by an SVG user agent:

The main svg element defines the image area in which all SVG graphics elements are drawn. Below svg, three main elements appear. SVG defines several elements that are not rendered on the screen, but give information about your content. One of these is title. (You can also create your own metadata elements, using alternate XML namespaces. As we'll will see later on, the ability to provide your own information is very useful for building applications on top of SVG.)

The second element, defs, contains the definitions that may be reused throughout the entire SVG file. That's the place where a content developer would put paint servers, style sheets, or scripting definitions. In this particular case, defs contains the definition of a linear gradient (an instance of a paint server) that fills elements (similar to the way the Gradient class that implements the Paint interface allows you -- in Java 2D -- to fill shapes).

The next element is a g (group) element that contains what is displayed on the screen (alternatively, this content could have been directly put under the image area element instead of being grouped). It consists of two graphics elements: a rectangle ( rect), and a piece of text ( text). The rectangle is filled using the gradient defined previously, and the text is filled using an RGB color. You can see that any SVG graphics element can be transformed, as with the text which, in this example, is scaled and skewed.

In this example, the XML presentation attributes ( "fill=", "stop-color=",...) have been used to style the SVG elements. Alternatively, Cascading Style Sheets (external, defined in the defs section or inlined) could have been used.

For more information on the SVG format, take a look at the W3C SVG web site where you can find links to most of the SVG resources available on the web.

If you're experienced with the Java 2D API, you can see that SVG has very similar capabilities. However, there's at least one big difference: Java 2D is a rendering API, while SVG is a structured graphics format. In point of fact, some third-party APIs -- such as ILOG JViews Component Suite -- exist on top of Java 2D to provide users with a structured graphics library. One advantage of using that toolkit (instead of directly using Java 2D) is that you no longer have to call Java 2D drawing primitives to leverage its rendering capabilities; instead, you can deal directly with structured objects that are directly linked to their business objects, without having to code an additional layer. You can also easily interact with the objects (select, move, or edit them) using high-level APIs, or even put built-in behaviors (such as the fact that the links of a network display are attached to nodes and "follow" them) into the structured objects.

Here is a snippet of ILOG JViews Graphics Framework code that does something very similar to what I just described:

// creates the objects manager
IlvManager manager = new IlvManager();
manager.setName("ILOG JViews Hello World! Example");
// creates a group
IlvGraphicSet g = new IlvGraphicSet();
// creates a generic path object using a Java 2D 
// Rectangle2D object as Shape
IlvGeneralPath rectangle = new IlvGeneralPath(new 
  Rectangle2D.Float(0, 0, 640, 480));
Color color1 = new Color(204, 204, 255);
Color color2 = new Color(102, 102, 204);
// creates a linear gradient Paint object with 3 steps
Paint gradient = new IlvLinearGradientPaint(0,0,1,0, 
  new float[] {0, 0.2, 1}, new Color[] {color1, color1, 
  color2}, true);
// sets the gradient on the generic path
rectangle.setFillPaint(gradient);
// adds the generic path to the group
g.addObject(rectangle, false);
// creates a text object at a certain position and 
// with a given text
IlvZoomableLabel text = new IlvZoomableLabel(new 
  IlvPoint(145, 140), "Hello World!");
// sets the color that will be used to draw the text
text.setFillPaint(new Color(255, 255, 102);
// adds the text to the group
g.addObject(text, false);
// adds the group to the objects manager
manager.addObject(g, false);

As you can see, the IlvManager instance is the global object that manages the structured graphics objects. As in SVG, you can group objects using an IlvGraphicSet. You can also create metadata, such as the title on the IlvManager object. With the ILOG JViews API, you can go further and add interactions and behaviors to objects. You also have the ability to load and save (leveraging the SVGGraphics2D code from Apache) SVG from the content of the IlvManager instance. This leverage lets your Java programs interoperate with SVG authoring tools or SVG user agents.

In addition to the Graphics Framework, the ILOG JViews Component Suite provides several modules built on top of the Graphics Framework to provide higher level interfaces. This makes it that much easier for you to build rich graphics applications.

The SDM (Stylable Data Mapper) module allows you to build graphics objects from a generic model, and style them using CSS. The other modules are dedicated to particular tasks. For example, the Graph Layout module lets you arrange networks of nodes and links, and the Gantt Chart module allows display of Gantt or Schedule Charts in Swing applications.

Build an SVG Web Application with Java

This section describes, step by step, how to build an SVG web-enabled application using the Java API of ILOG JViews. The sample application is a weather map that can be displayed on an SVG-enabled web browser client, and generated from a Servlet on a J2EE server using ILOG JViews. Developing such an application can be split into two main steps. The initial step is to import graphics into ILOG JViews and configure it for later use. The second step is to really develop the application (both its server and client sides).

Step 1: Import SVG graphics into the JViews Editor

ILOG JViews Graphics Framework provides a Swing-based editor to draw and edit ILOG JViews graphics objects. The ILOG JViews Composer (leveraging the Graphics Framework ability to import and export SVG) can also be used as an SVG editor.

In this particular case, a graphic artist has designed (with an SVG authoring tool) some drawings to represent a weather station on the map (thermometer, clouds, rain, and so forth). To leverage the graphics, we need to import them into ILOG JViews to link them to our business data (that is, the weather information). There are several ways we could proceed, but in this case, we leverage the ability of the ILOG JViews Composer to import a piece of SVG as the graphical representation of a JViews Prototype.

A JViews Prototype is a logical group of graphics objects, similar to the ones used in the first example (for example, IlvRectangle). In addition, these objects have different properties and behaviors linked to a business logic. This is exactly what we need here, since we want to modify the appearance of our graphics objects depending on external data (in this case, the weather center data).

To create such a Prototype, we choose the Create New Prototype button from the Composer toolbar. This pops up a Prototype Wizard that will help us throughout the process.

On the first page of the Wizard, you give the name of the Prototype to create, and then choose to import the visual representation of the Prototype from an SVG file.

After importing the graphics from the SVG file and showing you what will be the graphical representation of a weather station in your application, the Wizard asks if you want to add properties to the newly created Prototype; properties correspond to values in your business logic. In this case, we need to create several properties -- including temperature and windSpeed -- that correspond to their counterpart in the Weather Data Model.

Once a property has been created, in most cases the property will either trigger a change in the visual rendering of the Prototype, or initiate interactions when its value changes. That's what the next Wizard page shows you. Taking the example of the windSpeed property, we associate that property to a graphic effect that consists of scaling the blue arrow of the weather station. This arrow has to grow or reduce its size, depending on the wind speed. We can achieve that by choosing the Scale an Element option from the available geometric transformations on the page.

Once the Scale an Element option has been chosen, the Wizard lets you choose how to scale the element (depending on the property values). For example, the following Wizard page asks you to choose which element (in the graphical representation of the Prototype) to apply the transformation, and how it depends on the value of the windSpeed property.

Of course, this task has to be repeated for each property you want to associate to your JViews Prototype, and for each effect you want to create when that property is modified.

Now that we've imported the SVG graphics, we just save the Prototype to a JViews file to make it available to all ILOG JViews applications. The Prototype can be added in an IlvManager like any other object (rectangle, text, and so on), the only difference being that the Prototypes have business properties and effects bounded to them.

Step 2: Develop the SVG Client and the Java Server of the application running on a J2EE Server

The second step when building a typical SVG web-enabled application is to create the application itself. I'll first describe how to build the server-side application, which relies on an ILOG JViews Java Servlet subclass. I'll then explain how to create the client side using SVG.

Creating the Server Side: The WeatherCenter Class

We first have to fill an IlvManager with instances of the Prototype we created in the previous section. This can be done on the server by a background thread that gets weather data from the remote weather center server, and creates Prototype instances (according to this data) before filling the IlvManager.

As shown in the code below, the WeatherCenter class fills several IlvManager instances with the weather map of different countries:

import ilog.views.*;
import ilog.views.prototypes.*;
import ilog.views.svg.*;

public class WeatherCenter extends Thread {
  // the singleton instance of that class
  private final static WeatherCenter instance = 
    new WeatherCenter();

  // static variables for country names/keys
  private final static String USA = "USA";
  private final static String FRANCE = "France";

  // the Map that will contain an IlvManager instances 
  // for each country key
  private HashMap map = new HashMap();
  // a variable to indicate the thread should be stopped
  private boolean stop = false;

  private WeatherCenter() {
    // the two following lines are needed to load 
    // the Prototype we previously designed in the 
    // ILOG JViews Composer into the Prototype 
    // Library in memory.
    IlvGroupBag prototypeBag = new 
      IlvGroupBag(new IlvManager());
    prototypeBag.getManager().read("weatherstation.ivl");
    // we first deal with USA map
    IlvManager manager = new IlvManager();
    map.put(USA, manager);
    manager.setStreamFactory(new SVGStreamFactory());
    // we add USA SVG map in layer #0
    manager.read("usa.svg");
    // we get an instance of the Prototype we designed 
    // from the Library
    IlvPrototype station =
       IlvPrototypeLibrary.getPrototype("weatherstation", 
         "Weather Station");
    for (...) {
       IlvPrototypeInstance instance = 
         station.createInstance(town_name);
       IlvGraphic graphic = new IlvGraphicGroup(instance);
       graphic.move(x, y);
       boolean reDraw = false;
       // some stations are added in layer #1 some in #2
       if (small_town) {
         int layerIndex = 1;
         manager.addObject(graphic, layerIndex, reDraw);
       } else {
         int layerIndex = 2;
         manager.addObject(graphic, layerIndex, reDraw);
       }
    }
    manager.getLayer(1).addVisibilityFilter(new 
      IlvZoomFactorVisibilityFilter(3, 
      IlvZoomFactorVisibilityFilter.NO_LIMIT);
    // we now deal with France map in another 
    // IlvManager instance
    manager = new IlvManager();
    map.put(FRANCE, manager);
    // ...
  }

  // returns the singleton instance
  public static SVGWeatherCenter getInstance() {
    return instance;
  }

  // stop the thread
  public void end() {
    stop = true;
  }

  // returns the IlvManager instance for a given 
  // country name.
  public IlvManager getManager(String country) {
    return map.get(country);
  }

  public void run() {
    while (!stop) {
    // regularly, query the remote weather center 
    // server and update the Prototype instances 
    // properties depending on the new weather data.
    for (...) {
      // this modifies the graphical representation 
      // according to that new value.
      instance.set("windSpeed", value_from_weather_center);
    }
  }
}

Most of the code is in the constructor of the singleton class, where we register an IlvManager for each country, and fill it with several objects:

  • Before dealing with a particular country, we first create the corresponding IlvManager instance and register it for the corresponding country key:
IlvManager manager = new IlvManager();
map.put(USA, manager);
  • We then load a background map in SVG format for the country in the first layer (that map may have been exported to SVG by the ILOG JViews MapBuilder tool from a standard map format):
  manager.setStreamFactory(new SVGStreamFactory());
    manager.read("usa.svg");
  • We then load the Prototype we created with the ILOG JViews Composer from the Prototype Library:
  IlvPrototype station =
    IlvPrototypeLibrary.getPrototype("weatherstation", 
    "Weather Station");
  • We iterate on the different towns of the country to create Prototype instances for each town:
  for (...) {
  // create a Prototype instance from the Prototype 
  // for a particular town corresponding to a weather 
  // station
  IlvPrototypeInstance instance = 
    station.createInstance(town_name);
  // from that Prototype instance we create an 
  // IlvGraphic instance to be able to add the result 
  // to an ILOG JViews IlvManager
  IlvGraphic graphic = new IlvGraphicGroup(instance);
  // x,y are computed using JViews Maps module from 
  // longitude and latitude and move the weather 
  // station to that point
  graphic.move(x, y);
  // in our particular context we don't need to redraw 
  // as we are on server
  boolean reDraw = false;
  // some stations are added in layer #1 some in #2
  if (small_town) {
    // we put small towns in layer number 1
    int layerIndex = 1;
    manager.addObject(graphic, layerIndex, reDraw);
  } else {
    // we put big towns in layer number 2
    int layerIndex = 2;
    manager.addObject(graphic, layerIndex, reDraw);
  }
}

Using graphic.setTooltip(String), we could also add additional information for each graphic that would be displayed as a tooltip when viewing the SVG on the client.

  • And finally, we ask the manager not to display the layer number 1 (small towns) if the user doesn't zoom a bit (at least three times the initial value) on the map. This avoids showing too many stations at first glance; more stations can be discovered when zooming:
  manager.getLayer(1).addVisibilityFilter(new 
    IlvZoomFactorVisibilityFilter(3,
    IlvZoomFactorVisibilityFilter.NO_LIMIT);
   

The Java Servlet

Once this is done, we have to provide a way for the SVG client to get the content of these managers as SVG. For that purpose, ILOG JViews Graphics Framework provides a subclass of the Java HttpServlet class to generate SVG documents from the content of a JViews IlvManager. This class has an abstract method named getManager that must be defined so that the Servlet knows from which IlvManager it should generate the SVG content (depending on the HttpServletRequest it receives). For example:

import ilog.views.*;
import ilog.views.svg.*;
import ilog.views.svg.servlet.*;

public class SVGWeatherServlet extends 
  IlvSVGManagerServlet {
  // the object that allows you to configure SVG generation
  private static final SVGDocumentBuilderConfigurator 
    configurator = new SVGDocumentBuilderConfigurator();

  static {
    // we configure the SVG generator to load invisible 
    // layers on demand only.
    // for example the layer #1 will be downloaded 
    // only after zooming three times.
    configurator.setCompactMode(
      SVGDocumentBuilderConfigurator.COMPACT_LOD);
  }

  // the constructor of the Servlet just passes the 
  // configurator instance to the parent class.
  public SVGWeatherServlet() {
    super(configurator);
  }

  // when initializing the Servlet we also start the 
  // WeatherCenter thread
  public void init(ServletConfig config) {
    super.init(config);
    WeatherCenter.getInstance().start();
  }

  // when destroying the Servlet we also stop the 
  // WeatherCenter thread
  public void destroy() {
    super.destroy();
    WeatherCenter.getInstance().end();
  }

  public IlvManager getManager(HttpServletRequest 
    request) {
    // in that application we have several 
    // IlvManagers containing the weather data for 
    // several countries. We are returning the IlvManager
    // that corresponds to the particular request.
    return WeatherCenter.getInstance().getManager(
      request.getParameter("country"));
  }
}

Now the ILOG JViews implementation of the IlvSVGManagerServlet generates the SVG content and sends it to the client as soon as a request similar to the following one arrives on the server:

http://server.demo.org/SVGWeatherServlet?request=image& width=640&height=480&country=USA

Get the corresponding SVG DOM to enrich it with scripting and animation

For our example application, we want to add some additional features to the generated SVG file:

  • We want the rain to be animated under the cloud when it's raining.

  • We want to add a drop shadow around the background map of the country.

For that, we have to get the SVG Document Object Model (DOM) instance before sending it back to the client, in order to add these features that are not automatically added by the ILOG JViews SVG Servlet. This Servlet is designed such that you can get the DOM instance through the Java org.w3.dom.Document object, and customize it before returning it to the client. For that purpose, you have to redefine the following method:

protected Document generateSVGDocument(
  HttpServletRequest request, int width, int height,
  String[] requestedLayers)
     throws ServletException {
  // we first get the DOM instance from the parent class
  Document svgDOM = super.generateSVGDocument(request, 
    width, height, requestedLayers);
  // now we can modify the svgDOM before returning it back:
  // we want to put the definitions of the animations 
  // in a 'defs' section for that purpose, using the 
  // Java DOM API, we query the 'defs' elements
  // of the DOM and take the first one in the list.
  Element defs = svgDOM.getElementsByTagNameNS(SVG_NS, 
    "defs").item(0);
  for (...) {
    // we create an animation using an SVG 'animate' 
    // element for each weather station SVG element.
    Element animate = svgDOM.createElementNS(SVG_NS, 
      "animate");
    // we choose to animate a CSS property
    animate.setAttribute("attributeType","CSS");
    // which is the stroke dashoffset
    animate.setAttribute("attributeName", 
      "stroke-dashoffset");
    // we animate it from 3 to 0
    animate.setAttribute("from", "3");
    animate.setAttribute("to", "0");
    // during 0.5 seconds
    animate.setAttribute("dur", "0.5s");
    // and we repeat that operation indefinitely
    animate.setAttribute("repeatCount", "indefinite");
    // we link the animation to the current weather 
    // station SVG element
    animate.setAttributeNS(XLINK_NS, "xlink:href", town_id);
    // we put the animation in the 'defs' section 
    // we previously get.
    defs.appendChild(animate);
  }

  return svgDOM;
}

As you can see, an easy way to animate the rain falling is to use an SVG animate element to regularly change the stroke offset of the dashed lines representing the rain in the weather station. The DOM API (part of the Java 2 SDK v1.4, or available with the JAXP API) allows you to create DOM elements and update them dynamically. As we created an SVG animate element, we could create a filter element to achieve the drop-shadow effect using the advanced styling capabilities of SVG:

// the main filter element
Element filter = svgDOM.createElementNS(SVG_NS, "filter");
filter.setAttribute("id", "drop");
filter.setAttribute("filterUnits", "objectBoundingBox");
filter.setAttribute("x", "-0.1");
filter.setAttribute("y", "-0.1");
filter.setAttribute("width", "1.2");
filter.setAttribute("height", "1.2");
// the gaussian blur
Element blur = svgDOM.createElementNS(SVG_NS, "feGaussianBlur");
blur.setAttribute("in", "SourceAlpha");
blur.setAttribute("stdDeviation", "2");
blur.setAttribute("result", "balpha");
// the offset
Element offset = svgDOM.createElementNS(SVG_NS, "feOffset");
offset.setAttribute("in", "balpha");
offset.setAttribute("dx", "4");
offset.setAttribute("dy", "4");
offset.setAttribute("result", "oba");
// the merge between the offset and the source
Element merge = svgDOM.createElementNS(SVG_NS, "feMerge");
Element node = svgDOM.createElementNS(SVG_NS, "feMergeNode");
node.setAttribute("in", "oba");
merge.appendChild(node);
node = svgDOM.createElementNS(SVG_NS, "feMergeNode");
node.setAttribute("in", "SourceGraphic");
merge.appendChild(node);
filter.appendChild(blur);
filter.appendChild(offset);
filter.appendChild(merge);
// adds the result to the 'defs' section
defs.appendChild(filter);

And we then associate the filter we just defined with the background map SVG element:

svgDOM.getElementBy("map").setAttribute("filter", "url(#drop)");

To better understand the code above, let's look at the piece of SVG it will generate in the defs section:

<!-- we have a 'drop' filter that coordinates are defined 
accordingly to the bounding -->
<!-- rectangle of the SVG element we will put it on. -->
<filter id="drop" filterUnits="objectBoundingBox" x="-0.1" 
y="-0.1" width="1.2" height="1.2">
  <!-- the filter is first defining a gaussian blur that 
  is applied to the alpha channel -->
  <!-- of the targeted element -->
  <feGaussianBlur in="SourceAlpha" stdDeviation="2" 
  result="balpha"/>
  <!-- we then define a filter that is the result of the 
  gaussian blur offset by 4, 4 in x and y -->
  <feOffset in="balpha" dx="4" dy="4" result="oba"/>
  <!-- we then merge the result of the offset filter and 
  the initial source graphic -->
  <!-- to produce the final result -->
  <feMerge>
    <feMergeNode in="oba"/>
    <feMergeNode in="SourceGraphic"/>
  </feMerge>
</filter>

Creating the Client Side

On the client side, the application is simply an SVG file that has been designed to dialog with the server:

<?xml-stylesheet title="JViews Style Sheet" href="default.css" 
type="text/css"?>
<svg width="100%" height="100%"
     xmlns:ilv="http://xmlns.ilog.com/JViews/SVGToolkit"
     onload="JViewsSVG.Init(evt)">
  <defs>
    <script xlink:href="SVGFramework.es" type="text/ecmascript"/>
    <style type="text/css">
        <![CDATA[
           .tooltip {stroke:none}
        ]]>
    </style>
  </defs>
  <svg id="WeatherMap" x="0%" y="0%" width="100%" height="100%">
    <metadata>
      <ilv:view type="manager" enableTooltips="true" 
      xlink:href="SVGWeatherServlet?country=USA"/>
    </metadata>
  </svg>
  <svg x="0" y="0" width="240" height="240">
    <title>Weather Map OverView</title>
    <metadata>
      <ilv:view type="over" disableZoom="true" 
      xlink:href="#WeatherMap"/>
    </metadata>
  </svg>
</svg>

The first line is a processing instruction that calls the default JViews style sheet to style the SVG UI elements generated by ILOG JViews scripts included by the script element. Of course, leveraging CSS, this style can be overridden. For example, in the defs section, you can see that the tooltips style is redefined to remove the default stroke used by the default style and use none instead.

The outermost svg element represents the image area in which all the elements are drawn. As we've seen in the first section, metadata are very important for building applications on top of SVG. Furthermore, the SVG Recommendation encourages metadata to describe the graphics content. Here we are leveraging metadata to describe the two sub svg elements, to put data that is not purely graphical information on existing SVG elements:

  • The first sub svg element represents the main view corresponding to the content of our server side ILOG JViews IlvManager. It displays the map of the USA (and there are other files with different country parameters) and the different weather stations. The XLink href attribute is pointing to the Servlet we defined in the previous paragraph. Only the country parameter is set; the other parameters (the size of the image for example) are automatically set by the JViews scripts running on the client.
  • The second one is an overview of the main view, also using XLink href to reference the main view it should display the overview from. This view has the disableZoom attribute set, so that the user can't zoom on it.

These metadata are processed by the script that is launched through the call to the JViewsSVG.Init() function on the onload (see the attribute with the same name) event of the main svg element. This script is contained in the SVGFramework.es ECMAScript library we include through the script element.

This client-side file is a regular SVG file, and in addition to the ILOG JViews elements, you can add any kind of SVG elements you want to display in the web browser. For this application, you could add a piece of SVG that represents a "button" to allow the user to switch to the weather map of another country (using the SVG ability to provide hyperlinks):

<defs>
  <style type="text/css">
    <![CDATA[
      .button {stroke:black;fill:lightGrey;fill-opacity:0.9}
    ]]>
  </style>
</defs>
<!-- by surrounding a piece of SVG by an 'a' element you can -->
<!-- easily create a hyperlink that is activated when clicking -->
<!-- on that piece of SVG in a similar way to HTML -->
<a xlink:href="france.svg">
  <rect class="button" x="10" y="340" width="90" height="30"/>
  <text x="35" y="360">France</text>
</a>

Once this client-side SVG file and the Servlet are deployed, you just have to load the file in your favorite SVG user agent. Several software packages for displaying SVG are already available (and free of charge): Batik Squiggle SVG Viewer from Apache, or Adobe SVG Viewer. Using the latest software in your web browser, you will see the following result after zooming on the US east coast:

If you remember the windSpeed property example we worked with during the design of the Prototype, you can see that the wind blue arrows have different sizes depending on the wind speed. (There's also a property we didn't describe for changing arrow orientation according to the wind direction). You can also see the features we added by dynamically modifying the DOM instance, such as the drop-shadow effect around the map. And finally, the results of the client-side ECMAScript library are also visible, such as the overview with its yellow transparent rectangle that defines the part of the map you are looking at (relatively to the map of the whole country).

If you click on the France button defined in the client-side SVG file, you automatically switch to the French weather map. Below is the result of the Servlet under Batik Squiggle SVG Viewer:

A similar sample application is available on the ILOG sample web server

Summary

Hopefully, this article has shown you how easy it is to build and deploy an SVG web-enabled application on the Java platform with the help of the ILOG JViews Component Suite. You get a predefined SVG application with some built-in features (such as dynamic overview, and load-on-demand of layers). With the Document object representing the SVG DOM instance you can -- using the Java DOM API -- customize it before sending it back to an SVG user agent, to benefit from all the power of SVG (animation, high-end visual effects, and so forth).

A workflow diagram of the whole process is shown below. In the first step, a third-party authoring tool generates a piece of SVG as the graphical representation of a weather center. Then, inside two Swing-based applications, ILOG JViews Composer and MapBuilder, we build a JViews Prototype from the piece of SVG and an SVG map from a map database (not described in this article). Finally, a Servlet, running on a J2EE server, generates from the two previously created files the SVG display that will be shown in an SVG user agent.

Click to enlarge

Compared to other possible ways of deploying graphical applications on the client, the synergy of Java and SVG offers advantages at each step in the process. In the first step, you benefit from the fact that SVG implementations are widespread. Also, SVG is an open format that gives you interoperability and permits you to import drawings from artist authoring tools into the Java platform. On the server, you benefit from a Java implementation of the standard DOM API to create and modify the SVG content. And finally, leveraging SVG on the client brings to you the benefit of a standard format, thus allowing you to mix data from different standards, using a well-defined solution. In our example in this article, the SVG client mixes SVG graphical elements, CSS styling, and ILOG JViews XML metadata (belonging to their own namespace) for easy integration with SVG.

What's Next?

In the future, there should be many more devices on which SVG user agents can run. Leveraging the SVG 1.1 Recommendation, SVG viewers for constraints resources devices will certainly be developed, allowing you to visualize your applications under smaller devices, and bringing SVG power to J2ME platform devices. This will offer a broader range of deployment possibilities to your SVG applications and increase their interoperability.

Furthermore, the effort done by the SVG working group on integrating the SVG format with other presentation and interaction XML formats such as XForms (for high-level UI definition) or SMIL (for Multimedia and Animation) will allow you to leverage (in SVG) the additional features of those formats.

Finally, SVG is a great complement to the Java platform. It provides a new alternative for importing graphical data, and a new client-side deployment opportunity for Java server-side applications.

See Also

The Swing Connection

W3C SVG 1.0 Recommendation 

W3C SVG web site

ILOG JViews Component Suite web site

ILOG SVG Weather Map Demo

SVGGraphics2D paper

Apache Batik web site

Adobe SVG web site

About the Author

Christophe Jolif is a Software Architect who works on the ILOG JViews Component Suite. He has been involved with SVG since 1999, representing his company at the SVG W3C Working Group and participating in the Batik project at Apache.