« Roller 0.9.8.2 bug... | Main | Rave beta »

JSP Control Flow engine.

It's time for another installment in my ongoing series of articles on continuations in Java Web application development. In a previous installment I explained how I was able to rip the continuation-based Cocoon Control Flow engine free of Cocoon and make it work in a standalone unit test environment. For this installment, I have implemented a simple web application that uses that Control Flow engine for all application logic and uses JSP for presentation.

On the Cocoon web site, the Cocoon Control Flow tutorial uses the good-old Tomcat JSP number guess example to illustrate how the Cocoon Control Flow engine works, so I have done the same thing for my JSP Control Flow engine. There are five parts in my implementation of number guess: the numberguess.js JavaScript program that executes on the server side, a FlowServlet that starts and continues the JavaScript program, the Control Flow engine which runs the JavaScript program, the guess.jsp page which asks the user to guess, and the success.jsp page which informs the user of a successful guess.

I'm not going to go into any more detail on the FlowServlet or the Control Flow engine implementation at this time. The code is not yet packaged for release, but you can get it in the form of an Eclipse project here: JSPFlow-v1.zip (it's 2.4MB because it includes the way-too-many jars necessary for running MockRunner). I'll discuss FlowServlet implementation later, for now let's take a look at the JavaScript code for number guess.

function main(tray) {

  var random =  Math.round( Math.random() * 9 ) + 1;
  var hint = "No hint for you!"
  var guesses = 0;

  while (true) {

    // send guess page to user and wait for response
    forwardAndWait(tray, "guess.jsp", 
       { "random" : random, "hint" : hint, "guesses" : guesses} );

    // process user's guess
    var guess = parseInt( webapp.request.getParameter("guess") );
    guesses++;
    if (guess) {
      if (guess > random) {
        hint = "Nope, lower!"
      } 
      else if (guess < random) {
        hint = "Nope, higher!"
      } 
      else {
        // correct guess
        break;
      }
    }
  }

  // send success page to user
  forwardAndWait(tray, "sucess.jsp", 
     {"random" : random, "guess" : guess, "guesses" : guesses} );
}

As you can see, the code for my version of number guess is almost exactly the same as the code for the Cocoon version. There's no substantial difference. Now, let's take a look at guess.jsp. There are a couple of differences, but nothing major. Instead of the Cocoon ${thing} syntax, you see JSP syntax. Instead of making the continuation ID part of the POST URL as Cocoon Control Flow does, I've put the continuation ID in a hidden field.

<html>
<head>
  <title>JSPFlow number guessing game</title>
</head>
<body>
  <h1>Guess the Number Between 1 and 10</h1>
  <h2><%= request.getAttribute("hint") %></h2>
  <h3>You've guessed <%= request.getAttribute("guesses")%> times.</h3>
  <form method="post" action="/jspflow/FlowServlet">
    <input type="hidden" name="contid" value='<%=request.getAttribute("contid")%>' />
    <input type="text" name="guess"/>
    <input type="submit"/>
  </form>
</body>
</html>

Finally, let's take a look at the success.jsp. Again there is no substantial difference.

<html>
<head>
  <title>JSFlow number guessing game</title>
</head>
<body>
  <h1>Success!</h1>
  <h2>The number was: <%= request.getAttribute("random") %></h2>
  <h3>It took you <%= request.getAttribute("guesses")%> tries.</h3>
  <p><a href="/jspflow/FlowServlet">Play again</a></p>
</body>
</html>

Number guess is simple and not a very realistic. The input data is strings, all application logic is written in JavaScript, and the output data is also strings. In a real world application, we would probably want to call out to application logic written in Java and we would probably want to put some more complex objects into request scope for display on the JSP page. Despite that, I'm going to move on. I'll implement a more complex example once I've figured out how to make Control Flow work with Struts. In my next installment, I'll implement number guess again - this time using Struts and Control Flow.

Comments:

Have you thought about a name for this product?

Posted by Steve Shelley on March 29, 2004 at 11:11 AM EST #

I updated the init() method in your FlowServlet.java to make the paths to the javascript files relative. Once this is changed the 'web' folder deploys & runs nicely.
public void init() throws ServletException {
    try {
        ServletContext context = getServletContext();
        String rootPath = context.getRealPath("/");

        JavaScriptInterpreter interp = new JavaScriptInterpreter();
        interp.initialize();

        interp.register(rootPath+"/WEB-INF/classes/flow/system.js");
        interp.register(rootPath+"/WEB-INF/numberguess.js");
        /*
        interp.register("C:\\allfiles\\scratch\\JspFlow\\src\\flow\\system.js");
        interp.register("C:\\allfiles\\scratch\\JspFlow\\web\\WEB-INF\\numberguess.js");
        */
        context.setAttribute("controlFlow", interp);
    } catch (Exception e) {
        throw new ServletException("ERROR initializing Control Flow", e);
    }
}

Posted by James Shipley on June 29, 2004 at 09:20 PM EDT #

I updated the init() method in your FlowServlet.java to make the paths to the javascript files relative. Once this is changed the 'web' folder deploys & runs nicely.
public void init() throws ServletException {
    try {
        ServletContext context = getServletContext();
        String rootPath = context.getRealPath("/");

        JavaScriptInterpreter interp = new JavaScriptInterpreter();
        interp.initialize();

        interp.register(rootPath+"/WEB-INF/classes/flow/system.js");
        interp.register(rootPath+"/WEB-INF/numberguess.js");
        /*
        interp.register("C:\\allfiles\\scratch\\JspFlow\\src\\flow\\system.js");
        interp.register("C:\\allfiles\\scratch\\JspFlow\\web\\WEB-INF\\numberguess.js");
        */
        context.setAttribute("controlFlow", interp);
    } catch (Exception e) {
        throw new ServletException("ERROR initializing Control Flow", e);
    }
}

Posted by James Shipley on June 29, 2004 at 09:21 PM EDT #

Post a Comment:
  • HTML Syntax: NOT allowed

« Roller 0.9.8.2 bug... | Main | Rave beta »

Welcome

This is just one entry in the weblog Blogging Roller. You may want to visit the main page of the weblog

Related entries

Below are the most recent entries in the category Java, some may be related to this entry.