Number Guessing Game Example - Remote Edition

This example shows the number guessing game demonstrated in the previous example, but now we add a browser remote function call to show how easy it is to call server-side Javascript functions from client-side Javascript. Struts Flow provides a client Javascript library and server-side framework support for calling flow functions remotely from the client's web browser. Function calls on the server are executed in the flow so the global variable state is available to be read and modified. In this example, we add a "cheat" button that will let the user see the secret number, but penalize their number of guesses by 5. The two new parts to the example are in the flow code and the guess.jsp file.

Flow Code

Here is what the flow code looks like:

var random;
var guesses;

function main() {

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

  while (true) {

    // send guess page to user and wait for response.  Specify only cheat() 
    // can be called remotely.
    forwardAndWait("failure", 
       { "hint"    : hint,
         "guesses" : guesses},
       ["cheat"]);

    print("processing a user guess "+struts.param.guess);
    // process user's guess
    var guess = parseInt( struts.param.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("success", 
     {"random"  : random, 
      "guess"   : guess, 
      "guesses" : guesses} );
}

function cheat() {
    guesses += 5;
    return {"secret":random, "guesses":guesses};
}

The big change here is several variables have been moved to outside the function to allow access by the new cheat() function. The cheat() function adds 5 to the number of guesses then returns the secret number. Struts Flow converts the returned object into JSON and returns it to the client.

JSP Presentation

This example adds the "cheat" button to the number guessing form, guess.jsp. When pressed, the Javascript uses the clientFlow.js library to call the cheat() function on the server.

<?xml version="1.0"?>
<html>
<head>
  <title>Struts Flow number guessing game</title>
    <script type="text/javascript">
  <!--
function init() {
    this.contid = "<%=request.getAttribute("contid")%>";
    this.client = new ClientFlow("guess.do");
}   
function cheat() {
    result = client.call("cheat", contid);
    alert("The secret number is "+result.secret+". After applying a penalty, you have guessed "+result.guesses+" times");
    contid = result.contid;
}
    -->
  </script>
  <script type="text/javascript" src="clientFlow.js" />
</head>
<body onload="init()">

  <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="guess.do">
    <input type="hidden" name="contid" value='<%= request.getAttribute("contid") %>' />
    <input type="text" name="guess"/>
    <input type="submit"/>
    <input type="button" onclick="cheat()" value="Cheat" />
  </form>
  
</body>
</html>

The key to the function call executing in the server flow is passing the continuation id to the client flow instance.