Software Steeplechase

Hayden Steep’s development obstacle course. (Java, JEE, and beyond)

October 25, 2006

Creating a servlet with a self-contained web server

Filed under: Java, JEE

For those of us who haven’t become guru’s at developing user interfaces in Swing/SWT/.NET or other technologies used to develop GUI’s, (in other words web developers), there is an easy way to leverage your JEE skills to create stand alone programs. Just create a web application as you normally would, but instead of deploying your creation to an application server, deploy the application server to your application.

Jetty WebServer is one such application server that can be instantiated inside of a Java program and configured to handle web requests on a certain port. When your application has completed its task, just stop the web server and your super-servlet will exit.

Here are the 4 basic steps to turning your server application development skills into client-application development skills.

Step 1: Constructor

The constructor instantiates an instance of the Jetty embeddable web server. It adds itself as the servlet that should handle all incoming requests on port 8111. It then starts the server.

    private Server server;
    private Context context;

    public ExecServlet() {
        server = new Server(8111);
        context = new Context(server, "/", Context.SESSIONS);
        context.addServlet(new ServletHolder(this), "/*");
        try {
            server.start();
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

Step 2: Get/Post functionality

In the methods below is where your servlet will do whatever it is you want it to do. The programmer has the full power of the Java API and libraries at his disposal in order to launch a process, process user input, write files, etc.

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        if(request.getPathInfo().equals("/DoSomething")) {
            //Do Something and return a response.
        }
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        if(request.getPathInfo().equals("/PostSomething")) {
            //Do Something and return a response.
        }
    }

Step 3: Executing

The servlet’s main() method instantiates an instance of itself and then launches a browser to point to itself. The code in the example is Windows specific, but some conditionals and a check of system properties can make the servlet operational in other operating systems.

    public static void main(String[] args) {

      ExecServlet servlet = new ExecServlet();

        Runtime runtime = Runtime.getRuntime();
        String[] cmd = new String[4];
        cmd[0] = "cmd.exe";
        cmd[1] = "/C";
        cmd[2] = "start";
        cmd[3] = "http://localhost:8111/";
        try {
            runtime.exec(cmd);
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

Step 4: All Done

Some process or user created condition will signal that the application has completed running, and now it is time to close up shop and stop the web/application server.

if (request.getPathInfo().equals("/finish")) {

    try {
      server.stop();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
}

October 4, 2006

Comskip Monitor - A Java service

Filed under: Java, General

I used to own a VCR, but it broke down in the year 2000 and I never looked back. I had the mind set that Television will rot your brain and that there was nothing on worth watching, yet alone taping.

A marriage, busy job, and 2 kids later, I’ve rediscovered the joy of Vegging Out in front of the boob-tube. However, during my 1 hour time slot for watching, there was rarely anything on worth watching. So, I finally took the plunge and configured a PVR (Personal Video Recorder) system. I research Tivo (subscription fees), vs a stand-alone computer hooked up to my television (noise/up-front cost) and decided upon SageTV.

SageTV allowed me to leverage my existing home computer. All I had to do was install a TV Tuning Card, the Sage TV software, and a wireless device that connects to my television. The initial cost was about the price of a Tivo, but I don’t have subscription fees and I don’t have a noisy computer in my den.

There is a 3rd party commercial skipping program called Comskip that can be run on recorded video files that creates a text file containing the time indexes where commercials appear in the videos. The only problem with this program is that it has to be run manually. Manual goes against the very ease-of-use nature of PVR devices, so I decided to author a program that would run as a service which would automatically run Comskip on video files as SageTV created them.

Thus, Comskip Monitor was born. One of the more interesting challenges was making use of the Java Runtime and Process classes.

  Runtime runtime = Runtime.getRuntime();
  Process process = runtime.exec(cmd);
  int exitCode = process.waitFor();

Despite my best efforts, the executed program “Comskip” would always hang about a minute into processing. As it turns out, Windows processes have a stdout, errout, and stdin. The buffers for these streams aren’t very big, and if you don’t consume the output streams, the process will halt until you do.

  Process process = runtime.exec(cmd);
  StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "ERROR");
  StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), "OUTPUT");

  errorGobbler.start();
  outputGobbler.start();

  int exitCode = process.waitFor();

  //Stream Gobbler
  class StreamGobbler extends Thread
  {
    InputStream is;
    String type;

    StreamGobbler(InputStream is, String type)
    {
      this.is = is;
      this.type = type;
    }

    public void run()
    {
      try
      {
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String line=null;
        while ( (line = br.readLine()) != null)
        {
          System.out.println(type + ">" + line);
        }
      }
      catch (IOException ioe)
      {
        ioe.printStackTrace();
      }
    }
  }

This JavaWorld article is the best resource I could find for explaining the intricacies of launching external processes.

Writing a Java service is a great way to learn about threading, process handling, and synchronizing blocks of code.

If you happen to be running a Windows based video recording software, I also recommend trying out Comskip Monitor.

Get free blog up and running in minutes with Blogsome
Theme designed by Jay of onefinejay.com