Login

Rapid Development in Java

A few folks asked me how I built the mobile version of this website. Thus, I wanted to describe the process in this article.

Background and Goals
My current website (Public-Action.org) is built with the PHP content manage system (CMS) Drupal. I could add new functionality to the Drupal CMS. However, I thought this would be good chance to extend some of my other skills.

I decided to generate a new mobile view-able version of my web content using Java. That gives me an opportunity to explore some of the newer computer languages which run on Java Virtual Machine (JVM). For example, Clojure or Scala.

A lot of shops have a large inventory of business requirements implemented in Java. To me. Java is still relevant as a computer language. However, newer programmers tend to be versed in other computer languages. Thus, an exploration of extending our basic process with a newer computer language seems worthy.

In this article. we'll produce the basic functionality used to create to exiting mobile version (view-able) of this site (public-action.org).

Building the mobile version of our website.
Our current website generates a Rich Site Summary (RSS) feed. RSS in an xml representation of the sites content. The current site's layout design is built to render on a full size (desktop/laptop) web browser. The site's layout is defined by the domain specific language (DSL), Cascading Style Sheets (CSS).

Thus, we need to replace the current CSS with CSS that responds and re-sizes to fit a mobile device. Again, we will use the responsive layout and design provided by the Twitter Bootstrap Front-end Framework.

Process Overview
I don't want a completely automated process. I want to manually inspect and verify the new mobile content (site) before publishing.

I need to get the mobile site up and running as soon as possible. That allows me to field test the site. My experience is, for mobile content, you literally need to take a walk with your device and see what your content looks like, how it renders when you are on the road.

Thus, we will rapidly prototype and build this application. I don't need a lot of bells and whistles. A plain command line utility fits my needs.

Our process overview:

  • Save a copy of our current site's RSS feed to a file location on our local machine (save as an xml file).
  • Parse the XML file.
  • For each article:
    • Get the title.
    • Get the body.
  • Add the article to table of contents landing page (I.E. index.html)
  • Create a directory to store our new mobile web site.
  • For each new mobile web page:
    • Add references to new meta tags, CSS, JavaScript, etc.
  • Write the table of contents landing page.
  • Copy sites artifacts like Twitter Bootstrap, any custom static pages, etc. Copy in to our new directory.
  • Manually review the new site (I.E. use something like FireFox's Responsive Design View).
  • Finally move new directory to hosting or cloud service.

We are using two great libraries from the Apache Commons.

Commons IO The FileUtls class makes copying out static content directories and files a very simple task.

Commons Lang We need to un-escape all of the html in our RSS feed. The StringEscapeUtils class takes care of this for us.

Additional Requirements
I also need some way for folks to contact me. However, since the web is inundated with spammers, I want to be careful about how I display my contact information. I want it to be easy for human viewers and difficult for bots (automated spam programs).

I'll a small JavaScript program that dynamically renders my email address. Most spam bots are not intelligent enough to parse a JavaScript program for contact info. Not a bullet proof mechanism, but a little protection.

When we run our program, we want to set the output directory and RSS xml file names (and path locations). We don't want those values to be hard-coded (located in the Java listings).

Implementation Details
We use a Simple API for XML (SAX) to parse of XML. The main benefit of a SAX parser is, it reads the input (file) in portions. As it recognizes xml tags and attrbitues, the parser generates events. You program implements a handler which receives the event information sent by the SAX parser. In our case we build our object (a document) and then a set of nodes.

As a side note, once your become familiar with how the SAX parser works. It's fairly easy to migrate your program from one computer language to the next. For example, parsing a RSS feed with a SAX parser using PHP is really not that different in Java.

A SAX parser becomes less of a choice if the XML you need to parse is complex (E.G. a lot of nested structures). However, in our case, the RSS XML is fairly flat structure. We don't need to parse the body of our articles. Therefore, we don't need to do any complicated traversals.

Since the is a Java program, all our data structures are expressed in class objects:

  • Node - A node is a logical representation of a web page. A title and a body.
  • NodeList - A collection (list) of nodes.
  • NodeListHandler -- Responds to the SAX parser events and builds our node list.
  • NodeDoc - Transforms a single node in to a web page. Adds the <hmlt> tags, CSS references etc.
  • TocDoc - Creates a table of contents (index.html) web page.
  • DocSet - Writes everything to disk. Creates an output directory, creates a file for each article.
  • StasticResource - Writes our CSS and JavaScript files to our output directory. Copies other artifacts store locally into the output directory (E.G. cache manifest file, a custom mobile "about" web page,etc.
  • Convert -- Invokes the SAX parser, connects our message handlers. Allows the user to pass command line arguments to the program. For example, we want to set the output directory name each time we run the program.

Code Snippets
Here is our NodeListHandler implementation.

package handler;

import com.pa.data.Node;
import com.pa.data.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 *
 * @author lorinpa
 * 
 */
public class NodeListHandler extends DefaultHandler {
  private StringBuilder buffer = new StringBuilder();
  private NodeList list;
  private Node node;
  boolean start = false;
  
  @Override
  public void startElement(String namespaceURI, String localName,
          String qName, Attributes atts) throws SAXException {
      buffer.setLength(0);
      if (qName.equals("language")) {
        list = new NodeList();
        start = true;
      } else if (qName.equals("item") && start) {
        node = new Node();
    }
  }

  @Override
  public void endElement(String uri, String localName, String qName) throws SAXException {
    if (start) {
        if (qName.equals("title")) {
          node.setTitle(buffer.toString());
        } else if (qName.equals("description")) {
          node.setBody(buffer.toString());
        } else if (qName.equals("item")) {
          list.add(node);
          node = new Node();
        }
    }
  }

  @Override
  public void characters(char[] ch, int start, int length) {
    buffer.append(ch, start, length);
  }

  public NodeList get() {
    return list;
  }
}

Not too complicated. You have to look at an actual RSS XML document to appreciate the processing. A few of the xml tages we are interested in (E.G. <item>) are used to summarize the XML document itself. Later in the document the same <item> tags are used to delimit our articles.

The SAX parser reads through the XML document sequentially. One of the tags that is located in the header is called <location>. So we look to see if we have read the location tag, if we have we are done with the header. If we haven't we are still reading the header.

Once the SAX parser moves past the header section, all we have to do is look for:

  • item -- Delimits an article.
  • title -- Yep, delimits the title of the article.
  • description -- Delimits the body of the article.

We store the data when we reach the closing tag. The close tag event is processed in endElement().

File System Artifacts and Locations
The Java program itself is packaged in to a single file (mobile-feed-convert.jar). You would run the program from the command line as such:

$my-dev> java -jar rss2MobileSite.jar -src "somedir/filename.xml"  -out "May-28-13"

So "java -jar mobile-feed-convert.jar" runs the Java run time and instructs to run the main method stored in the file rss2MobileSite.jar

-src is a command line argument. You include the full path (directories and folders) along with the RSS file name. For example,
/home/mydir/download/may-28-13-rss.xml

-out is also a command line argument. It tells the program to create a sub-directory relative to where you are running the command from. For example. you are running the program from /home/mydiir/mob-convert. If you specify -out "05-28-13", the program will create an output directory of "/home/mydir/mob-convert/05-28-13". That's where the mobile version of the site is stored (when the program is done running).

The location defaults are not difficult to change. I set them based on my own person preference.

I also wrote a custom build script for Apache's Ant utility. The build for this program is very simple. The only portion worth noting is the jar file manifest (see the make-jar task here. You need a manifest located in the jar file to make the jar file executable. The manifest defines which class contains the program entry point. The whole build can be performed with Java's command line tools. You don't have to use a build tool like Apache Ant or Maven. The Ant build just saves a few strokes.

To summarize, this was a rapid build. I spent a few hours knocking this release out. It's not fancy, but it perform the "must have" functions.

I've placed all of the source code on the git hub repository here.

About the Author:
Lorin M Klugman - I'm an experienced developer. My main interest is in new technology. Please use our contact box here if you are interested in hiring me. Please no recruiters :)