Storing state on the server

The application state should usually not be saved on the client. There may be some special case in addition to the one where you write educational code and want to demonstrate how to do it. Generally, the state of the application related to the actual use is stored in the session object or on some database. This is especially important when the application requests the user to enter a lot of data and does not want the user to lose the work if there is some hiccup in the client computer.

You spend a lot of time selecting the appropriate items in an online shop, choosing the appropriate items that work together, creating a configuration of your new model airplane, and all of a sudden, there is a blackout in your home. If the state were stored on the client you'd have had to start from scratch. If the state is stored on the server, the state is saved to disk; the servers are duplicated, fed by battery-backed power supplies, and when you reboot your client machine when the power comes back in your home, you log in, and miraculously, the items are all there in your shopping basket. Well, it is not a miracle; it is web programming.

In our case, the second version will store the state of the game in the session. This will let the user have the game restore so long as the session is there. If the user quits and restarts the browser, the session gets lost and a new game can start.

Since there is no need to send the actual colors and matching in hidden fields this time, the HTML generation is modified a bit, and the generated HTML will also be simpler:

<html> 
<head>
<link rel="stylesheet" type="text/css" href="colors.css">
<title>Mastermind guessing</title>
<body>
<form method="POST" action="master">
<div class="color3"></div>
<div class="spacer"></div>
<div class="color2"></div>
<div class="spacer"></div>
<div class="color1"></div>
<div class="spacer"></div>
<div class="color0"></div>
<div class="spacer"></div>0
<div class="spacer"></div>2<p>
<div class="color5"></div>
...
<div class="spacer"></div>
<div class="color1"></div>
<div class="spacer"></div>
<input type="text" name="full2" value="0" size="1"><input type="text" name="partial2" value="0" size="1">
<p>
<input type="submit" value="submit">
</form>
</body>
</head></html>

The number of full and partially matching colors is displayed as a simple number, so this version does not allow cheating or changing previous results. (These are the numbers 0 and 2 after the div tags that have the CSS class spacer.)

The handle method in MastermindHandler also changes, as shown in the following:

public void handle(HttpServletRequest request, 
HttpServletResponse response)
throws ServletException, IOException {

Game game = buildGameFromSessionAndRequest(request);
Guess newGuess = guesser.guess();
response.setContentType("text/html");
PrintWriter out = response.getWriter();
if (game.isFinished() || newGuess == Guess.none) {
displayGameOver(out);
} else {
log.debug("Adding new guess {} to the game", newGuess);
game.addGuess(newGuess, 0, 0);
sessionSaver.save(request.getSession());
displayGame(out);
}
bodyEnd(out);
}

This version of the class gets a SessionSaver object injected by the Guice injector. This is a class that we create. This class will convert the current Table into something that is stored in the session, and it also recreates the table from the data stored in the session. The handle method uses the buildGameFromSessionAndRequest method to restore the table and to add the full and partial match answers that the user just gave in the request. When the method creates a new guess and fills it in the table, and also sends it to the client in the response, it saves the state in the session by calling the save method via the sessionSaver object.

The buildGameFromSessionAndRequest method replaces the other version, which we named buildGameFromRequest:

private Game buildGameFromSessionAndRequest(HttpServletRequest request) { 
Game game = buildGameFromMap(sessionSaver.restore(request.getSession()));
Map<String, String> params = toMap(request);
int row = getLastRowIndex(params);
log.debug("last row is {}", row);
if (row >= 0) {
final int full = Integer.parseInt(params.get(html.paramNameFull(row)));
final int partial = Integer.parseInt(params.get(html.paramNamePartial(row)));
log.debug("setting full {} and partial {} for row {}", full, partial, row);
table.setPartial(row, partial);
table.setFull(row, full);
if (full == table.nrOfColumns()) {
game.setFinished();
}
}
return game;
}

Note that this version has the same illness of using the parseInt method from the Integer class in JDK, which throws an exception.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.163.238