Tutorial -> Task 1 -> Step 3: Submitting edits

Submitting a Form

In this step, you will learn how to:
• Check form default parameter values
• Create a request from a form
• Override the default parameter values in a request
• Submit a form and get a response

We now have a form which can generate POST requests to define the betting pool. Our next step will be to build the code which handles these requests. We will start by simply recording changes, and defer validation until the administrator attempts to open the pool. For our demonstration application, we will use in-memory persistence only, and will provide ourselves with a way to clear it so that each JUnit test can run independantly.

Testing pool display

The first thing we want to test and implement is the display of the current state of the pool. We will do this by setting the state directly, using the supplied entity classes and then invoke the form to display the pool. At this time, we will also add the set up code to clear the pool before each test:

public void setUp() throws Exception {
    BettingPool.reset();
}

public void testPoolDisplay() throws Exception {
    BettingPool.getGames()[0].setAwayTeam( "New York Jets" );                                // (1) set up data
    BettingPool.getGames()[0].setHomeTeam( "Philadelphia Eagles" );
    BettingPool.getGames()[2].setAwayTeam( "St. Louis Rams" );
    BettingPool.getGames()[2].setHomeTeam( "Chicago Bears" );
    BettingPool.setTieBreakerIndex(2);

    ServletRunner sr = new ServletRunner( "web.xml" );
    ServletUnitClient client = sr.newClient();
    client.setAuthorization( "aUser", "pool-admin" );
    WebResponse response = client.getResponse( "http://localhost/PoolEditor" );

    WebForm form = response.getFormWithID( "pool" );
    assertNotNull( "No form found with ID 'pool'", form );

    assertEquals( "Away team 0", "New York Jets", form.getParameterValue( "away0" ) );       // (2) check team names
    assertEquals( "Home team 0", "Philadelphia Eagles", form.getParameterValue( "home0" ) );
    assertEquals( "Away team 1", "", form.getParameterValue( "away1" ) );
    assertEquals( "Home team 1", "", form.getParameterValue( "home1" ) );
    assertEquals( "Away team 2", "St. Louis Rams", form.getParameterValue( "away2" ) );
    assertEquals( "Home team 2", "Chicago Bears", form.getParameterValue( "home2" ) );

    assertEquals( "Tie breaker game", "2", form.getParameterValue( "tiebreaker" ) );         // (3) check radio button
}

Here we are:

  1. Setting up the data that the servlet which read to create the entry form. Here we are using a simple in-memory persistence strategy. If the servlet accessed the database, we would have to do JDBC calls here.
  2. Reading the names of the teams and comparing them to what we initialized. Note the test for the skipped game to verify that the defaults come through.
  3. Checking the state of the radio button. Note that we can use the same method WebForm.getParameterValue for each parameter, no matter its type.

As before, the above test should initially fail. We then make it work by changing the loop in printBody as follows:

    BettingPoolGame[] games = BettingPool.getGames();
    for (int i = 0; i < games.length; i++) {
        pw.println( "<tr><td><input name='home" + i + "' value='" + games[i].getHomeTeam() + "' ></td>" );
        pw.println( "<td><input name='away" + i + "' value='" + games[i].getAwayTeam() + "'></td>" );
        pw.print( "<td><input type='radio' name='tiebreaker' value='" + i + "'" );
        if (i == BettingPool.getTieBreakerIndex()) pw.print( " checked" );
        pw.println( " /></td></tr>" );
    }

Testing pool entry

Now that we know we can display the current state of the pool, we will verify that we can use the form to change it as well:

public void testPoolEntry() throws Exception {
    ServletRunner sr = new ServletRunner( "web.xml" );
    ServletUnitClient client = sr.newClient();
    client.setAuthorization( "aUser", "pool-admin" );
    WebResponse response = client.getResponse( "http://localhost/PoolEditor" );

    WebForm form = response.getFormWithID( "pool" );
    assertNotNull( "No form found with ID 'pool'", form );

    form.setParameter( "away1", "Detroit Lions" );                           // (1) enter values into the form
    form.setParameter( "home1", "Denver Broncos" );
    form.setParameter( "tiebreaker", "1" );

    SubmitButton saveButton = form.getSubmitButton( "save", "Save" );        // (2) select the desired submit button
    response = form.submit( saveButton );                                    // (3) submit the form

    assertEquals( "Away team 0", "", form.getParameterValue( "away0" ) );    // (4) verify the response
    assertEquals( "Home team 0", "", form.getParameterValue( "home0" ) );
    assertEquals( "Away team 1", "Detroit Lions", form.getParameterValue( "away1" ) );
    assertEquals( "Home team 1", "Denver Broncos", form.getParameterValue( "home1" ) );

    assertEquals( "Tie breaker game", "1", form.getParameterValue( "tiebreaker" ) );
}

This is our first form submission. Take note:

  1. We make a call for each parameter that we want to set. Any parameters we do not set will be submitted with their default values.
  2. Since there is more than one button in the form, we ask for the one we want by name and value.
  3. We submit the form, specifying the desired button.
  4. We can use the same methods as above to check the new state of the pool. Alternately, we could have examined the BettingPool object directly.

This test will fail with a 405 response, since we have not defined a handler for the POST message. We do so now:

protected void doPost( HttpServletRequest request, HttpServletResponse response )
        throws ServletException, IOException {
    updateBettingPool( request );
    response.setContentType( "text/html" );
    PrintWriter pw = response.getWriter();

    pw.println( "<html><head></head><body>" );
    printBody( pw );
    pw.println( "</body></html>" );
}

void updateBettingPool( HttpServletRequest request ) {
    BettingPoolGame[] games = BettingPool.getGames();
    for (int i = 0; i < games.length; i++) {
        games[i].setAwayTeam( request.getParameter( "away" + i ) );
        games[i].setHomeTeam( request.getParameter( "home" + i ) );
    }
    BettingPool.setTieBreakerIndex( getTieBreakerIndex( request ) );
}

private int getTieBreakerIndex( HttpServletRequest request ) {
    try {
        return Integer.parseInt( request.getParameter( "tiebreaker" ) );
    } catch (NumberFormatException e) {
        return 0;
    }
}

Note that we are using the same printBody method as the doGet method does.

We now have the ability to edit the pool entries. Our next step is to add the validation and handle opening the pool to bettors.