Chapter: Internet & World Wide Web HOW TO PROGRAM - Rich Internet Application Server Technologies - Web Services

| Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail |

Creating a Blackjack Web Service

Our next example is a web service that assists you in developing a blackjack card game.

Creating a Blackjack Web Service

 

Our next example is a web service that assists you in developing a blackjack card game. The Blackjack web service (Fig. 28.13) provides web methods to shuffle a deck of cards, deal a card from the deck and evaluate a hand of cards. After presenting the web service, we use it to serve as the dealer for a game of blackjack (Fig. 28.14). The Blackjack web service uses an HttpSession object to maintain a unique deck of cards for each client ap-plication. Several clients can use the service at the same time, but web method calls made by a specific client use only the deck of cards stored in that client’s session. Our example uses the following blackjack rules:

 

Two cards each are dealt to the dealer and the player. The player’s cards are dealt face up. Only the first of the dealer’s cards is dealt face up. Each card has a value. A card numbered 2 through 10 is worth its face value. Jacks, queens and kings each count as 10. Aces can count as 1 or 11—whichever value is more beneficial to the player (as we will soon see). If the sum of the player’s two initial cards is 21 (i.e., the player was dealt a card valued at 10 and an ace, which counts as 11 in this situation), the player has “blackjack” and immediately wins the game—if the dealer does not also have blackjack (which would result in a “push”—i.e., a tie). Otherwise, the player can begin taking additional cards one at a time. These cards are dealt face up, and the player decides when to stop taking cards. If the player “busts” (i.e., the sum of the player’s cards exceeds 21), the game is over, and the player loses. When the player is sat-isfied with the current set of cards, the player “stands” (i.e., stops taking cards), and the dealer’s hidden card is revealed. If the dealer’s total is 16 or less, the dealer must take another card; otherwise, the dealer must stand. The dealer must continue taking cards until the sum of the dealer’s cards is greater than or equal to 17. If the dealer exceeds 21, the player wins. Otherwise, the hand with the higher point total wins. If the dealer and the player have the same point total, the game is a “push,” and no one wins. Note that the value of an ace for a dealer depends on the dealer’s other card(s) and the casino’s house rules. A dealer typically must hit for totals of 16 or less and must stand for totals of 17 or more. However, for a “soft 17”—a hand with a total of 17 with one ace counted as 11—some casinos require the dealer to hit and some require the dealer to stand (we require the dealer to stand). Such a hand is known as a “soft 17” because taking another card cannot bust the hand.

 

The web service (Fig. 28.13) stores each card as a String consisting of a number, 113, representing the card’s face (ace through king, respectively), followed by a space and a digit, 03, representing the card’s suit (hearts, diamonds, clubs or spades, respectively). For example, the jack of clubs is represented as "11 2", and the two of hearts is represented as "2 0". To create and deploy this web service, follow the steps presented in Sections 28.3.2–28.3.3 for the HugeInteger service.

 

154   // Fig. 28.13: Blackjack.java

 

155   // Blackjack web service that deals cards and evaluates hands

 

156   package com.deitel.iw3htp4.ch28.blackjack;

4

203   import java.util.ArrayList;

 

204   import java.util.Random;

 

205   import javax.annotation.Resource;

 

206   import javax.jws.WebService;

 

207   import javax.jws.WebMethod;

 

208 import javax.jws.WebParam;

 

209 import javax.servlet.http.HttpSession;

 

210 import javax.servlet.http.HttpServletRequest;

 

211 import javax.xml.ws.WebServiceContext;

 

212 import javax.xml.ws.handler.MessageContext;

213        

205 @WebService( name = "Blackjack", serviceName = "BlackjackService" )

 

206 public class Blackjack

207 {

 

208       // use @Resource to create a WebServiceContext for session tracking

 

209       private @Resource WebServiceContext webServiceContext;

 

210       private MessageContext messageContext; // used in session tracking

 

211       private HttpSession session; // stores attributes of the session

23

1             // deal one card

 

2             @WebMethod( operationName = "dealCard" )

 

3             public String dealCard()

4             {

 

5                    String card = "";

29

7                    ArrayList< String > deck =

 

8                          ( ArrayList< String > ) session.getAttribute( "deck" );

9              

10                 card = deck.get( 0 ); // get top card of deck

 

11                 deck.remove( 0 ); // remove top card of deck

12           

39                 return card;

 

40          } // end WebMethod dealCard

41           

1             // shuffle the deck

 

2             @WebMethod( operationName = "shuffle" )

 

3             public void shuffle()

4             {

 

5                    // obtain the HttpSession object to store deck for current client

 

6                    messageContext = webServiceContext.getMessageContext();

 

7                    session = ( ( HttpServletRequest ) messageContext.get(

 

8                          MessageContext.SERVLET_REQUEST ) ).getSession();

47

9                    // populate deck of cards

 

10                 ArrayList< String > deck = new ArrayList< String >();

11           

19                 for ( int face = 1; face <= 13; face++ ) // loop through faces

 

20                       for ( int suit = 0; suit <= 3; suit++ ) // loop through suits

53                      deck.add( face + " " + suit ); // add each card to deck

54

24                 String tempCard; // holds card temporarily during swapping

 

25                 Random randomObject = new Random(); // generates random numbers

 

26                 int index; // index of randomly selected card

58

31                 for ( int i = 0; i < deck.size() ; i++ ) // shuffle

32                 {

 

33                       index = randomObject.nextInt( deck.size() - 1 );

34           

36                       // swap card at position i with randomly selected card

 

37                       tempCard = deck.get( i );

 

38                       deck.set( i, deck.get( index ) );

 

39                       deck.set( index, tempCard );

 

40                 } // end for

68

41                 // add this deck to user's session

 

42                 session.setAttribute( "deck", deck );

 

43          } // end WebMethod shuffle

72

46          // determine a hand's value

 

47          @WebMethod( operationName = "getHandValue" )

 

48          public int getHandValue( @WebParam( name = "hand" ) String hand )

49          {

 

50                 // split hand into cards

 

51                 String[] cards = hand.split( "\t" );

 

52                 int total = 0; // total value of cards in hand

 

53                 int face; // face of current card

 

54                 int aceCount = 0; // number of aces in hand

82

53                 for ( int i = 0; i < cards.length; i++ )

54                 {

 

55                       // parse string and get first int in String

 

face = Integer.parseInt(

87        cards[ i ].substring( 0, cards[ i ].indexOf( " " ) ) );

88       

89        switch ( face )

90        {

 

           

91        case 1: // if ace, increment aceCount

92        ++aceCount;

93        break;

94        case 11: // jack

95        case 12: // queen

96        case 13: // king

97        total += 10;

98        break;

99        default: // otherwise, add face

100      total += face;

101      break;

102      } // end switch

103      } // end for

 

104

105      // calculate optimal use of aces

106      if ( aceCount > 0 )

107      {

 

108      // if possible, count one ace as 11

109      if ( total + 11 + aceCount - 1 <= 21 )

110      total += 11 + aceCount - 1;

 

111      else // otherwise, count all aces as 1

 

112      total += aceCount;

113      } // end if

114

115      return total;

 

116      } // end WebMethod getHandValue

 

117      } // end class Blackjack

 

Fig. 28.13 | Blackjack web service that deals cards and evaluates hands.

 

Session Tracking in Web Services

The Blackjack web service client first calls method shuffle (lines 40–71) to shuffle the deck of cards. This method also places the deck of cards into an HttpSession object that is specific to the client that called shuffle. To use session tracking in a Web service, you must include code for the resources that maintain the session state information. In the past, you had to write the sometimes tedious code to create these resources. JAX-WS, how-ever, handles this for you via the @Resource annotation. This annotation enables tools like Netbeans to “inject” complex support code into your class, thus allowing you to focus on your business logic rather than the support code. The concept of using annotations to add code that supports your classes is known as dependency injection. Annotations like @Web-Service, @WebMethod and @WebParam also perform dependency injection.

 

Line 20 injects a WebServiceContext object into your class. A WebServiceContext object enables a web service to access and maintain information for a specific request, such as session state. As you look through the code in Fig. 28.13, you’ll notice that we never create the WebServiceContext object. All of the code necessary to create it is injected into the class by the @Resource annotation. Line 21 declares a variable of interface type MessageContext that the web service will use to obtain an HttpSession object for the current client. Line 22 declares the HttpSession variable that the web service will use to manipulate the session state information.

 

Line 44 in method shuffle uses the WebServiceContext object that was injected in line 20 to obtain a MessageContext object. Lines 45–46 then use the MessageContext object’s get method to obtain the HttpSession object for the current client. Method get receives a constant indicating what to get from the MessageContext. In this case, the constant MessageContext.SERVLET_REQUEST indicates that we’d like to get the HttpServlet-Request object for the current client. We then call method getSession to get the HttpSession object from the HttpServletRequest object.

 

Lines 49–70 generate an ArrayList representing a deck of cards, shuffle the deck and store the deck in the client’s session object. Lines 51–53 use nested loops to generate Strings in the form "face suit" to represent each possible card in the deck. Lines 59–67 shuffle the deck by swapping each card with another card selected at random. Line 70 inserts the ArrayList in the session object to maintain the deck between method calls from a particular client.

Lines 25–37 define method dealCard as a web method. Lines 30–31 use the session object to obtain the "deck" session attribute that was stored in line 70 of method shuffle. Method getAttribute takes as a parameter a String that identifies the Object to obtain from the session state. The HttpSession can store many Objects, provided that each has a unique identifier. Note that method shuffle must be called before method dealCard is called the first time for a client—otherwise, an exception occurs at line 33 because get-Attribute returns null at lines 30–31. After obtaining the user’s deck, dealCard gets the top card from the deck (line 33), removes it from the deck (line 34) and returns the card’s value as a String (line 36). Without using session tracking, the deck of cards would need to be passed back and forth with each method call. Session tracking makes the dealCard method easy to call (it requires no arguments) and eliminates the overhead of sending the deck over the network multiple times.

Method getHandValue (lines 74–116) determines the total value of the cards in a hand by trying to attain the highest score possible without going over 21. Recall that an ace can be counted as either 1 or 11, and all face cards count as 10. This method does not use the session object because the deck of cards is not used in this method.

 

As you’ll soon see, the client application maintains a hand of cards as a String in which each card is separated by a tab character. Line 78 tokenizes the hand of cards (rep-resented by hand) into individual cards by calling String method split and passing to it a String containing the delimiter characters (in this case, just a tab). Method split uses the delimiter characters to separate tokens in the String. Lines 83–103 count the value of each card. Lines 86–87 retrieve the first integer—the face—and use that value in the switch statement (lines 89–102). If the card is an ace, the method increments variable aceCount. We discuss how this variable is used shortly. If the card is an 11, 12 or 13 (jack, queen or king), the method adds 10 to the total value of the hand (line 97). If the card is anything else, the method increases the total by that value (line 100).

 

Because an ace can have either of two values, additional logic is required to process aces. Lines 106–113 of method getHandValue process the aces after all the other cards. If a hand contains several aces, only one ace can be counted as 11. The condition in line 109 determines whether counting one ace as 11 and the rest as 1 will result in a total that does not exceed 21. If this is possible, line 110 adjusts the total accordingly. Otherwise, line 112 adjusts the total, counting each ace as 1.

 

Method getHandValue maximizes the value of the current cards without exceeding 21. Imagine, for example, that the dealer has a 7 and receives an ace. The new total could be either 8 or 18. However, getHandValue always maximizes the value of the cards without going over 21, so the new total is 18.


Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail


Copyright © 2018-2020 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.