| Sign In/My Account | View Cart |
Building Modular Applications with Seppia
Pages: 1, 2
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. Link-Vision querying the O'Reilly website
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:
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.
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.
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.
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 |
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:
java
-cp . StartUp into its installation directory. This drastically reduces the need
for a batch or shell script.
zip it from its root directory and unzip it somewhere else without any
extra work.
Lorenzo Puccetti is a software developer/architect living and working in London, England.
Return to ONJava.com.
Showing messages 1 through 11 of 11.