ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Building Modular Applications with Seppia
Pages: 1, 2

Building a Sample Application

Once you understand the basics of using JavaScripts with Seppia, it is time to build something a little more challenging with it. The application we want to build is a simple GUI that provides a chart about the domains extension distribution of outlinks from any HTML page. The application should allow the user to type any URL, retrieve the web page, find the links in the HTML tags, and provide a chart of their distribution. We call this application Link-Vision. Figure 2 shows it in action.

Figure 2
Figure 2. Link-Vision querying the O'Reilly website

Decomposing The Application

The first step is to think how to design this application as separate components. Even without the help of an object-oriented guru, it seems obvious that the charting aspect of the application has nothing to do with finding the HTML links. It follows that we are going to have two modules:

  • One to parse the HTML to find its links.
  • One to draw a chart component.

We call these modules org.link-vision.html-analyzer and org.link-vision.chart, respectively, and prepare manually the folders for them.


myFirstSeppia
    +--- jars
    +--- modules
    |       +--- org.seppia.bootstrap
    |       |              +--- javascripts
    |       |                      +--- StartUp.js
    |       |
    |       +--- org.link-vision.html-analyzer
    |       |              +--- javascripts
    |       |              +--- jars
    |       |
    |       +--- org.link-vision.chart
    |                      +--- javascripts
    |                      +--- jars
    |
    +--- StartUp.class

The next step is to search for some existing products to reuse in our modules. This leads to the following two open source products:

Please note that at this point, while I do like these products, many alternatives are available. My choice was purely driven by the constraints of the sample application. Choosing the right tool to embed into your software system still remains a significant job. Only by reusing suitable, mature, tested products can we reduce the effort in creating new applications.

Once we have downloaded the HTML parser, we can copy htmlparser.jar from its lib directory into org.link-vision.html-analizer/jars. Similarly, for the JFreeChart we can copy jfreechart-0.9.21.jar and jcommon-0.9.6.jar (the code from JFreeChart relies upon the work in JCommon) into org.link-vision.chart/jars.

Building The HTML Parser

Now we can finally define the services provided by our modules by writing the appropriate JavaScripts. For org.link-vision.html-analyzer, we write the JavaScript LinkFinder.js to provide a function to extract the links from a URL.


var URL =    java.net.URL
var LinkTag= Packages.org.htmlparser.tags.LinkTag;
var Parser=  Packages.org.htmlparser.Parser;
var NodeClassFilter =
  Packages.org.htmlparser.filters.NodeClassFilter;

/*
This function returns a JavaScript object with
one method  that given a url string gives you an
array of URLs (outlinks from the given url)
*/
function main()
{
   var obj = new Object();
   obj.getLinks = getLinks;
   return obj;
}

function getLinks(url)
{
   var f = new NodeClassFilter(LinkTag);
   var parser = new Parser (url);
   var list = parser.extractAllNodesThatMatch(f);
   var array = [];
   for (var i = 0; i < list.size (); i++)
   {
      var linkTag =  list.elementAt(i);
      // skip if no http link.
      if (linkTag.isHTTPLink()==false) continue;
      var link = linkTag.extractLink();
      // skip any relative link.
      if (link =="" ) continue;
      array[array.length] = new URL(link);
   }
   return array;
}

Although this JavaScript makes usage of some unfamiliar classes from the HTMLParser API, it should be quite easy to read. The point here is that to the other modules, org.link-vision.html-analyzer is just a provider of a service to get the links from a URL. Its implementation is hidden between the JavaScript code and htmlparser.jar and could be easily changed or rewritten to use different .jars. Provided that the JavaScript object continues to return the function getURL (the only contract exposed by the module), its implementation is free to change.

It might not seem as powerful as we want to make it, but this feature effectively decouples major subsystems of your architecture from each other, which is crucial for building successful large systems.

Building The Chart

Let's move back to the other module. For org.link-vision.chart, we write a JavaScript, PieBuilder.js, that creates a JavaScript object with two methods:

  • createPair(name,value) creates a pairing of a name and a numeric value (e.g., createPair("ibm", 80); ).
  • createGUIComponent(title) creates a Swing component (specifically, the pie chart).

Here's the implementation:


var JLabel =      Packages.javax.swing.JLabel;
var ImageIcon =   Packages.javax.swing.ImageIcon;
var ChartFactory =
  Packages.org.jfree.chart.ChartFactory;
var DefaultPieDataset =
  Packages.org.jfree.data.general.DefaultPieDataset;

var pieDataset_ = new DefaultPieDataset();

function main()
{
   pieDataSet_ = new DefaultPieDataset();
   obj = new Object();
   obj.createPair = createPair;
   obj.createGuiComponent = createGuiComponent;
   return obj;
}

function createPair(name, value)
{
   pieDataset_.setValue(name,value);
}

function createGuiComponent(title)
{
   var chart = ChartFactory.createPieChart(
                 title,pieDataset_,true,true,true);
   var image = chart.createBufferedImage(500,400);
   var lblChart = new JLabel();
   lblChart.setIcon(new ImageIcon(image));
   return lblChart;
}

Once again, despite the fact that there may be few classes unfamiliar to you, the code should be quite easy to read.

Gluing The Modules Together

Now that we have completed the two modules, we need a third one to combine them together. We call this module org.link-vision.application and write one JavaScript: Main.js.

Main.js uses the functionality of the two previous modules to create the Swing application. It is important to note that the module does not need additional .jars.


var HashMap =      java.util.HashMap;
var Integer =      java.lang.Integer;
var BorderLayout = java.awt.BorderLayout;
var ActionListener=java.awt.event.ActionListener;
var JLabel =       Packages.javax.swing.JLabel;
var JPanel =       Packages.javax.swing.JPanel;
var JFrame =       Packages.javax.swing.JFrame;
var JTextField =   Packages.javax.swing.JTextField;

function main()
{
   // creates the LinkFinder object.
   var linkFinder = run(
      "org.link-vision.html-analyzer",
      "LinkFinder");
   var panel = new JPanel(new BorderLayout());
   var txtURL = new JTextField(
      "http://www.java.sun.com");

   txtURL.addActionListener(function f()
   {
      // actionListener implementation.
      var url = txtURL.getText();
      var array = linkFinder.getLinks(url);
      var map = new HashMap();

      // loops thru all the urls updating
      // the map: extensionName --> count.
      for (var i=0;i<array.length;i++)
      {
         var host = array[i].getHost();
         var extension =
           host.substring(1+host.lastIndexOf('.'));
         if (map.containsKey(extension))
         {
            var t = new Integer(1+
               (map.get(extension)).intValue());
            map.put(extension,t);
         }
         else
         {
            map.put(extension,new Integer(1));
         }
      }

      // creates the pieBuilder object.
      var pieBuilder = run("org.link-vision.chart",
          "PieBuilder");
      var iterator = map.keySet().iterator();
      while (iterator.hasNext())
      {
         var ext = iterator.next();
         var hitsCount = map.get(ext);

         // creates the pairs.
         pieBuilder.createPair(ext,hitsCount);
      }

      // creates the component for the main panel
      var component=pieBuilder.createGuiComponent(
         "Domain Extensions Distribution");
      panel.removeAll();
      panel.add(component,BorderLayout.CENTER);
      panel.revalidate();
      panel.repaint();
   });

   var f = new JFrame("Link-Vision");
   f.getContentPane().add(txtURL,BorderLayout.NORTH);
   f.getContentPane().add(panel,BorderLayout.CENTER);
   f.setSize(510,470);
   f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   f.setVisible(true);
}

Now there is only one piece missing from this jigsaw puzzle: if you recall, Seppia starts up by executing the JavaScript StartUp.js in org.seppia.bootstrap. This JavaScript needs to be redirected to execute the JavaScript org.link-vision.application Main.js:

function main()
{
   run("org.link-vision.application","Main");
}

That's it--all done. If you have managed to follow all of the instructions up to this point, you should be able to run Link-Vision.

This is how the directory structure should look:


myFirstSeppia
   +--- jars   // the classes to bootstrap Seppia
   +--- modules
   |       +--- org.seppia.bootstrap
   |       |          +--- javascripts
   |       |                    +--- StartUp.js
   |       |
   |       +--- org.link-vision.application
   |       |          +--- javascripts
   |       |                    +--- Main.js
   |       |
   |       +--- org.link-vision.html-analyzer
   |       |          +--- javascripts
   |       |          |      +--- LinkFinder.js
   |       |          +--- jars
   |       |                 +--- htmlparser.jar
   |       |
   |       +--- org.link-vision.chart
   |              +--- javascripts
   |              |          +--- PieBuilder.js
   |              +-jars
   |                  +--- jfreechart-0.9.21.jar
   |                  +--- jcommon-0.9.6.jar
   |
   +--- StartUp.class


Related Reading

Jakarta Commons Cookbook
By Timothy M. O'Brien

Final Considerations

Having finished the application, you might wonder whether it was worth the effort. Of course, you could have written this application as a standard Java program, but if you had done so, you would have missed some of the benefits that come with the Seppia technology. Here's a short list of some of the most significant benefits:

  • Seppia applications are classpath-less. Any Seppia application is launched by typing java -cp . StartUp into its installation directory. This drastically reduces the need for a batch or shell script.
  • Seppia applications are elegant and modular. Seppia technology sets precise rules of where to place .jars, JavaScripts and other resources. This is reflected in a very neat and well-defined directory structure for any Seppia application. Developers should be able to immediately recognize a Seppia application and its constituent parts by looking at its structure.
  • Seppia provides an easy means for prototyping. Because Seppia uses JavaScript as a glue among its modules, it is easy to test new behaviors. The instructions could not be easier: change a JavaScript and restart your application. No code to compile, classes to patch, .jars to substitute. Also note that sometimes modifying well-written JavaScript code can be as simple (and certainly more powerful) as changing configuration files.
  • Seppia applications are ready to ship. Seppia is self-contained. A typical Seppia application incorporates all of its resources (.jars, JavaScripts, images, other files) in its modules. You should be able to zip it from its root directory and unzip it somewhere else without any extra work.
  • Seppia applications are extensible. The fact that Seppia is centered around an architecture for dynamic discovery of modules makes it by definition extensible. If you think about it, any Seppia application is just an extension of the existing Seppia installation. The Seppia installation is itself a Seppia application; perhaps the smallest: the least common denominator.

Resources

  • Download sample code for this article.
  • Seppia: The official website of Seppia. It provides a few introductory articles and some other documentation.
  • Rhino: The JavaScript engine used by Seppia. It provides some examples on how to use JavaScript to manipulate Java objects.
  • Mozilla: JavaScript: A good place to find resources on the JavaScript language.
  • e4x: A new technology integrated in Seppia to manipulate XML more effectively.

Lorenzo Puccetti is a software developer/architect living and working in London, England.


Return to ONJava.com.