[webbeans-commits] Webbeans SVN: r2513 - doc/trunk/reference/en-US.
webbeans-commits at lists.jboss.org
webbeans-commits at lists.jboss.org
Sun Apr 19 05:55:51 EDT 2009
Author: peteroyle
Date: 2009-04-19 05:55:50 -0400 (Sun, 19 Apr 2009)
New Revision: 2513
Modified:
doc/trunk/reference/en-US/environments.xml
Log:
added documentation for Swing Number Guess SE example
Modified: doc/trunk/reference/en-US/environments.xml
===================================================================
--- doc/trunk/reference/en-US/environments.xml 2009-04-19 09:50:29 UTC (rev 2512)
+++ doc/trunk/reference/en-US/environments.xml 2009-04-19 09:55:50 UTC (rev 2513)
@@ -276,12 +276,399 @@
<literal>StartMain</literal>.
</para>
</note>
-
-
</section>
+ <section>
+ <title>Swing Example: Number Guess</title>
+ <para>Here's an example of a Swing application, Number Guess, similar to the example in
+ chapter 3.4. In the Number Guess application you get given 10 attempts
+ to guess a number between 1 and 100. After each attempt,
+ you will be told whether you are too high, or too low. This example can be found in the
+ <literal>examples/se/numberguess</literal> folder of the Web Beans distribution.
+ </para>
+
+ <para>There is an empty <literal>beans.xml</literal> file in the root package
+ (<literal>src/main/resources/beans.xml</literal>), which marks this application as a Web Beans
+ application.
+ </para>
+
+ <para>The game's main logic is located in <literal>Game.java</literal>. Here is the code for
+ that class, excluding that which is identical to the JSF version: </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="scope" coords="1" />
+ <area id="name" coords="1" />
+ <area id="messages" coords="26" />
+ <area id="validation" coords="39" />
+ <area id="reset" coords="68" />
+ </areaspec>
+ <programlisting role="JAVA"><![CDATA[@ApplicationScoped
+public class Game implements Serializable
+{
+
+ private int number;
+ private int guess;
+ private int smallest;
+
+ @MaxNumber
+ private int maxNumber;
+
+ private int biggest;
+ private int remainingGuesses;
+ private boolean validNumberRange = true;
+
+ @Current Generator rndGenerator;
+
+ ...
+
+ public boolean isValidNumberRange()
+ {
+ return validNumberRange;
+ }
+
+ public boolean isGameWon()
+ {
+ return guess == number;
+ }
+
+ public boolean isGameLost()
+ {
+ return guess != number && remainingGuesses <= 0;
+ }
+
+ public boolean check()
+ {
+ boolean result = false;
+
+ if ( checkNewNumberRangeIsValid() )
+ {
+ if ( guess > number )
+ {
+ biggest = guess - 1;
+ }
+
+ if ( guess < number )
+ {
+ smallest = guess + 1;
+ }
+
+ if ( guess == number )
+ {
+ result = true;
+ }
+
+ remainingGuesses--;
+ }
+
+ return result;
+ }
+
+ private boolean checkNewNumberRangeIsValid()
+ {
+ return validNumberRange = ( ( guess >= smallest ) && ( guess <= biggest ) );
+ }
+
+ @PostConstruct
+ public void reset()
+ {
+ this.smallest = 0;
+ ...
+ this.number = rndGenerator.next();
+ }
+}]]></programlisting>
+ <calloutlist>
+ <callout arearefs="scope">
+ <para>
+ The bean is application scoped instead of session scoped, since an instance of the
+ application represents a single 'session'.
+ </para>
+ </callout>
+ <callout arearefs="name">
+ <para>
+ The bean is not named, since it doesn't need to be accessed via EL
+ </para>
+ </callout>
+ <callout arearefs="messages">
+ <para>There is no JSF <literal>FacesContext</literal> to add messages to. Instead the <literal>Game</literal> class provides
+ additional information about the state of the current game including:
+ </para>
+
+
+ <itemizedlist>
+ <listitem>
+ <para>If the game has been won or lost</para>
+ </listitem>
+ <listitem>
+ <para>If the most recent guess was invalid</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>This allows the Swing UI to query the state of the game, which it does
+ indirectly via a class called <literal>MessageGenerator,</literal> in order to determine the appropriate
+ messages to display to the user during the game.
+ </para>
+ </callout>
+ <callout arearefs="validation">
+ <para>
+ Validation of user input is performed during the <literal>check()</literal> method, since there is
+ no dedicated validation phase
+ </para>
+ </callout>
+ <callout arearefs="reset">
+ <para>
+ The <literal>reset()</literal> method makes a call to the injected <literal>rndGenerator</literal> in order to get the
+ random number at the start of each game. It cannot use
+ <literal>manager.getInstanceByType(Integer.class, new AnnotationLiteral<Random>(){})</literal>
+ as the JSF example does because there will not be any active contexts like
+ there is during a JSF request.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>The <literal>MessageGenerator</literal> class depends on the current instance of <literal>Game</literal>, and queries
+ its state in order to determine the appropriate messages to provide as the
+ prompt for the user's next guess and the response to the previous guess.
+ The code for <literal>MessageGenerator</literal> is as follows:
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="game" coords="3" />
+ <area id="challenge" coords="5" />
+ <area id="result" coords="16" />
+ </areaspec>
+ <programlisting role="JAVA"><![CDATA[public class MessageGenerator
+{
+ @Current Game game;
+
+ public String getChallengeMessage()
+ {
+ StringBuilder challengeMsg = new StringBuilder( "I'm thinking of a number between " );
+ challengeMsg.append( game.getSmallest() );
+ challengeMsg.append( " and " );
+ challengeMsg.append( game.getBiggest() );
+ challengeMsg.append( ". Can you guess what it is?" );
+
+ return challengeMsg.toString();
+ }
+
+ public String getResultMessage()
+ {
+ if ( game.isGameWon() )
+ {
+ return "You guess it! The number was " + game.getNumber();
+ } else if ( game.isGameLost() )
+ {
+ return "You are fail! The number was " + game.getNumber();
+ } else if ( ! game.isValidNumberRange() )
+ {
+ return "Invalid number range!";
+ } else if ( game.getRemainingGuesses() == Game.MAX_NUM_GUESSES )
+ {
+ return "What is your first guess?";
+ } else
+ {
+ String direction = null;
+
+ if ( game.getGuess() < game.getNumber() )
+ {
+ direction = "Higher";
+ } else
+ {
+ direction = "Lower";
+ }
+
+ return direction + "! You have " + game.getRemainingGuesses() + " guesses left.";
+ }
+ }
+}]]></programlisting>
+ <calloutlist>
+ <callout arearefs="game">
+ <para>
+ The instance of <literal>Game</literal> for the application is injected here.
+ </para>
+ </callout>
+ <callout arearefs="challenge">
+ <para>
+ The <literal>Game</literal>'s state is interrogated to determine the appropriate
+ challenge message.
+ </para>
+ </callout>
+ <callout arearefs="result">
+ <para>
+ And again to determine whether to congratulate, console or
+ encourage the user to continue.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>Finally we come to the <literal>NumberGuessFrame</literal> class which provides the Swing
+ front end to our guessing game. </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="gameIn" coords="3" />
+ <area id="messagesIn" coords="4" />
+ <area id="start" coords="6" />
+ <area id="init" coords="18" />
+ <area id="guess" coords="34" />
+ <area id="replay" coords="44" />
+ <area id="refresh" coords="50" />
+ </areaspec>
+ <programlisting role="JAVA"><![CDATA[public class NumberGuessFrame extends javax.swing.JFrame
+{
+ private @Current Game game;
+ private @Current MessageGenerator msgGenerator;
+
+ public void start( @Observes @Deployed Manager manager )
+ {
+ java.awt.EventQueue.invokeLater( new Runnable()
+ {
+ public void run()
+ {
+ initComponents();
+ setVisible( true );
+ }
+ } );
+ }
+
+ private void initComponents() {
+
+ buttonPanel = new javax.swing.JPanel();
+ mainMsgPanel = new javax.swing.JPanel();
+ mainLabel = new javax.swing.JLabel();
+ messageLabel = new javax.swing.JLabel();
+ guessText = new javax.swing.JTextField();
+ ...
+ mainLabel.setText(msgGenerator.getChallengeMessage());
+ mainMsgPanel.add(mainLabel);
+
+ messageLabel.setText(msgGenerator.getResultMessage());
+ mainMsgPanel.add(messageLabel);
+ ...
+ }
+
+ private void guessButtonActionPerformed( java.awt.event.ActionEvent evt )
+ {
+ int guess = Integer.parseInt(guessText.getText());
+
+ game.setGuess( guess );
+ game.check();
+ refreshUI();
+
+ }
+
+ private void replayBtnActionPerformed( java.awt.event.ActionEvent evt )
+ {
+ game.reset();
+ refreshUI();
+ }
+
+ private void refreshUI()
+ {
+ mainLabel.setText( msgGenerator.getChallengeMessage() );
+ messageLabel.setText( msgGenerator.getResultMessage() );
+ guessText.setText( "" );
+ guessesLeftBar.setValue( game.getRemainingGuesses() );
+ guessText.requestFocus();
+ }
+
+ // swing components
+ private javax.swing.JPanel borderPanel;
+ ...
+ private javax.swing.JButton replayBtn;
+
+}]]></programlisting>
+ <calloutlist>
+ <callout arearefs="gameIn">
+ <para>
+ The injected instance of the game (logic and state).
+ </para>
+ </callout>
+ <callout arearefs="messagesIn">
+ <para>
+ The injected message generator for UI messages.
+ </para>
+ </callout>
+ <callout arearefs="start">
+ <para>
+ This application is started in the usual Web Beans SE way, by observing the
+ <literal>@Deployed Manager</literal> event.
+ </para>
+ </callout>
+ <callout arearefs="init">
+ <para>
+ This method initialises all of the Swing components. Note the use
+ of the <literal>msgGenerator</literal>.
+ </para>
+ </callout>
+ <callout arearefs="guess">
+ <para>
+ <literal>guessButtonActionPerformed</literal> is called when the 'Guess' button is clicked, and
+ it does the following:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Gets the guess entered by the user and sets it as the current guess in the <literal>Game</literal></para>
+ </listitem>
+ <listitem>
+ <para>Calls <literal>game.check()</literal> to validate and perform one 'turn' of the game</para>
+ </listitem>
+ <listitem>
+ <para> Calls <literal>refreshUI</literal>. If there were validation errors with the input, this
+ will have been captured during <literal>game.check()</literal> and as such will be reflected
+ in the messeges returned by <literal>MessageGenerator</literal> and subsequently presented
+ to the user. If there are no validation errors then the user will be told
+ to guess again (higher or lower) or that the game has ended either in a
+ win (correct guess) or a loss (ran out of guesses).
+ </para>
+ </listitem>
+ </itemizedlist>
+ </callout>
+ <callout arearefs="replay">
+ <para>
+ <literal>replayBtnActionPerformed</literal> simply calls <literal>game.reset()</literal> to start a new game
+ and refreshes the messages in the UI.
+ </para>
+ </callout>
+ <callout arearefs="refresh">
+ <para>
+ <literal>refreshUI</literal> uses the <literal>MessageGenerator</literal> to update the messages to the user based
+ on the current state of the Game.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ To run this example simply
+ <itemizedlist>
+ <listitem>
+ <para>Open a command line/terminal window in the
+ <literal>examples/se/numberguess</literal> directory</para>
+ </listitem>
+ <listitem>
+ <para>Ensure that Maven 2 is installed and in your PATH</para>
+ </listitem>
+ <listitem>
+ <para>Ensure that the <literal>JAVA_HOME</literal> environment variable is pointing to your JDK installation</para>
+ </listitem>
+ <listitem>
+ <para>execute the following command</para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <programlisting>mvn -Drun</programlisting>
+
+ </section>
+
</section>
</chapter>
\ No newline at end of file
More information about the weld-commits
mailing list