Software Steeplechase

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

November 13, 2007

Enabling Validation in Struts 2

Filed under: Java, Struts 2

I’ve been learning Struts 2 recently.

I spent too much time figuring out that in order to enable the framework’s validation behavior, your action classes must extend the ActionSupport class.

The documentation fails to mention this small fact. Maybe it’s common knowledge to experienced Xwork developers, but wasn’t to me. I was very excited to be writing my new web application using POJO’s that didn’t extend any classes, but it looks like you have to unless you feel like rolling your own validation utilities.

Before I started using Struts 2, I learned everything i could about it so that I could be productive with it right away. However, I’ve been learning too much about this framework via the TIAS (try it and see) approach.

I signed up for an Apache confluence account hoping that I’d be able to edit the wiki to supplement the documentation, but am not sure who to contact to get right permissions to the docs.

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.

August 16, 2006

Virtual Java Interview ‘06 (Breadth of knowledge VS. Depth of knowledge)

Filed under: Java, General

canidate (smiling): Thank you for taking the time to see me. I’m excited about becoming a web developer for Turbo-MegaWidgets.

interviewer (smiling): No problem. I’m glad you could come in on such short notice. Why don’t you start by telling me about the technology you are familiar with.

interviewer (straight-faced): For example, we would like someone who knows how to program in Java, C#, Ruby, Python, Perl, PHP, C++, and Lisp. Can you do this for us?

canidate (forlorn): I’m sorry, but I’m only experienced with Java and know very little about those other programming languages.

interviewer (jolly): Ha ha ha ha! That’s perfectly ok! We focus on Java technology here at Turbo-MegaWidgets. I just use that as an ice-breaker to assure you that we don’t focus on breadth of knowledge here. As long as you have expertise, or depth of knowledge as we like to say, then you’ll do just fine!

canidate (relieved): Whew! That’s good to know, because it would be hard to become proficient in so many different areas of technology.

interviewer (smiling): No kidding. I’m glad to be doing business analysis these days, the thought of it makes me shiver. Anyhow, let’s get back to the interviewing shall we?

interviewer (straight-faced): We’re looking for a Java developer who has an in-depth understanding of using the Rational Unified Process, Extreme Programming, or Agile Methodologies to implement EJBs, Servlets, JSP, Velocity, Custom Tag Libraries, JSTL, XML, Ant, Maven, JUnit, TestNG, JDBC, Hibernate, iBATIS, Struts, Tapestry, Java Server Faces, Javascript, AJAX, GWT, Spring (all of it), AspectJ, WebServices, SOAP, how to configure CVS, BugZilla, Tomcat, JBoss, HypersonicDB, MySQL, Apache Web Server, Eclipse or another IDE, and an Applet in a twisted pair tree.

canidate (jolly): Heh heh heh! You almost got me again!

interviewer (straight-faced): I’m not joking this time.

canidate (nervous): Oh… well…. I created a Javascript “rollover” one time… on a JSP…

interviewer (dismissive): Don’t call us. We’ll call you.

While talking with a contact recently, he marveled at the breadth of knowledge you had to have in order to be a competent web developer. The explosion of frameworks and tools over the last 10 years has had the affect of putting more responsibilities on fewer engineers.

When I started professional web development only a few years back in 1998, there were dedicated programmers responsible for framework architecture, configuration and build management, database design and maintenance, and so on. This setup had the by-product of allowing each programmer to develop an expertise, or depth of knowledge, in the area for which he was responsible. It was easy to bring new-hires into this environment because it wasn’t essential that they ‘knew everything’, but more important that they were bright and could immerse themselves in their duties.

Today there are many tasks that have been made easier through the use of good tools. It would be financially irresponsible to pay the same number of developers to fill roles with narrow scopes. This has benefited developers by allowing them to be involved with more aspects of projects than was previously possible. This increased responsibility requires a breadth of knowledge that makes developers feel important (humility aside, something most of us care about a great deal), but it also puts a burden of responsibility on us to stay on the upward curve. Whereas the old teams depended on many smart developers, the new teams depend on smart and studious developers.

August 2, 2006

Maximizing Struts page flow re-use

Filed under: Java, Struts

In Struts, form’s must be bound to a specific action. Because of this, developers might create nearly identical Forms, say in JSP, in order to perform 2 distinct actions… Create vs Update.

Example:

 <!-- CreateFoo.jsp -->
 <html :form action="CreateFoo">
   <html :text property="name"/>
   <html :text property="description"/>
 </html>    

 <!-- UpdateFoo.jsp -->
 <html :form action="UpdateFoo">
   <html :text property="name"/>
   <html :text property="description"/>
 </html>

In this scenario, the only thing that is different between the two JSP’s, is the Action that will be initiated when the form is submitted. It would be nice to have 1 form that could be used whether the system is trying to create OR update.

One approach to solving this problem would be to use Tiles and put the form fields into a separate file.

 <!-- CreateFoo.jsp -->
 <html :form action="CreateFoo">
   <tiles :insert attribute="FooFields"/>
 </html>

While this implementation would reduce some duplication, you would still end up with 3 JSP’s rather than just 1, or even 2 as in the previous example.

So, what do we do then? The trick is to re-think what you are trying to accomplish, and develop actions that are fine-grained enough to use in either scenario. In other words, when the user wants to CreateFoo or UpdateFoo, in each situation they want to EditFoo. So, instead of thinking about the 2 flows as atomic units of work, they can be broken down as:

CreateFoo = (1) Show FooForm (2) Edit FooData (3) Create Foo

UpdateFoo = (1) Show FooForm (2) Edit FooData (3) Update Foo

The 2 distinct flows show signs of commonality and we end up with 1 JSP that can be used in either the Create or Update flow.

Example:

 <!-- EditFoo.jsp -->
 <html :form action="EditFoo">
   <html :text property="name"/>
   <html :text property="description"/>
 </html>

Now the question is… How do I incorporate the single ‘Edit’ page into an Update or Create Flow?

First of all, don’t try to define the page flows for the Create or Update flows outright, just access the Create or Update action mappings and let those actions delegate responsibility to other actions for the data they require.

Example:

<action path="/CreateFoo"
  type="my.action.CreateFoo"
  name="FooForm">
    <forward name="success" path="/FooSummary.jsp"/>
    <forward name="noFormData" path="/EditFoo.jsp"/>
</action>

<action path="/UpdateFoo"
  type="my.action.UpdateFoo"
  name="FooForm">
    <forward name="success" path="/FooSummary.jsp"/>
    <forward name="noFormData" path="/EditFoo.jsp"/>
</action>

<action path="/EditFoo"
  type="my.action.EditForm"
  input="/EditFoo.jsp"
  name="FooForm">
    <forward name="success" path="/Exit.do"/>
</action>

When the Create/Update flows are invoked, they will check to see if the FooForm contains any data. If not, those actions can return a forward that will cause the EditFoo.jsp to be displayed.

The only problem left is, to return control back to the ‘calling’ actions.

Note that the /EditFoo action mapping invoked /Exit.do upon successful completion (which is just the submission of the EditForm without any validation errors). So how do we tell Exit.do where to go?

Create a Stack in the session called ExitForwards. An action mapping would then add itself to the stack whenever it chains to a delegate flow, like when Create or Update flows branch off to the Edit flow.

An easy way to do this is to create a subclass of the Struts ActionForward called ExitForward.

package my.forward.ExitForward

public class ExitForward extends org.apache.struts.action.ActionForward
{}

Not one of your more complicated classes is it?

Then in your action mappings, just indicate that a forward is an ExitForward by simply specifying the ExitForward class type in the action mapping.

<action path="/CreateFoo"
  type="my.action.CreateFoo"
  name="FooForm">
    <forward name="success" path="/FooSummary.jsp"/>
    <forward name="noFormData" path="/EditFoo.jsp"
      className="my.forward.ExitForward"/>
</action>

<action path="/UpdateFoo"
  type="my.action.UpdateFoo"
  name="FooForm">
    <forward name="success" path="/FooSummary.jsp"/>
    <forward name="noFormData" path="/EditFoo.jsp"
      className="my.forward.ExitForward"/>
</action>

The only thing left to do is override the RequestProcessor to Push the current ActionMapping onto the ExitForwardStack (in the Session) whenever a forward of type ExitForward is returned.

//Override the RequestProcessor (or TilesRequestProcessor)
protected void processForwardConfig(HttpServletRequest request, HttpServletResponse response,
    ForwardConfig forward) throws IOException, ServletException {
  if (forward != null) {
    if (forward instanceof ExitForward) {
      Stack exitForwardStack = (Stack)request.getSession().getAttribute("ExitForwardStack");
      ActionForward redirectForward = new ActionForward();
      redirectForward.setRedirect(true);
      redirectForward.setPath(this.processPath(request, response));
      exitForwardStack.push(redirectForward);
    }
  }
  super.processForwardConfig(request, response, forward);
}

Then just wire up your Exit.do mapping and Action class

<action path="/Exit"
  type="my.action.GetExitForward"/>


  public class GetExitForward extends Action{

    public ActionForward Execute(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response) throws Exception{
      Stack exitForwardStack = (Stack)request.getSession().getAttribute("ExitForwardStack");
      ActionForward forward = (ActionForward)exitForwardStack.pop();
      return forward;
    }
  }

That’s all there is to it. With these modifications, you can transform your Struts application into a lean, mean, re-use machine. Applying these changes will allow you to re-use proven functionality in flows without having to create a lots of unnecessary action mappings and JSP’s.

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