Chapter 2. Developing applications using JBoss EAP You can start developing applications by using JBoss Tools with the Eclipse integrated development environment (IDE) and the JBoss EAP 8.0 quickstart examples. Note JBoss Tools is deprecated in JBoss EAP 8.0. No enhancements will be made to this feature, and it might be removed in a future release. 2.1. Overview JBoss Tools is a set of Eclipse-based plug-ins that enhance support for JBoss EAP technology. JBoss Tools works with the Eclipse integrated development environment (IDE). Note JBoss Tools is deprecated in JBoss EAP 8.0. No enhancements will be made to this feature, and it might be removed in a future release. Important JBoss Tools is a community project and is not supported by Red Hat. Please reference the community website for assistance with setting up and running your instance of JBoss Tools. To download JBoss Tools, see JBoss Tools Downloads . Many quick start code examples are provided with JBoss EAP 8.0 to help users get started writing applications using different Jakarta EE technologies. You can use JBoss Tools to run the quick start examples. Additional resources For more information about tested JBoss Tools versions, see Red Hat JBoss Enterprise Application Platform (EAP) and JBoss Tools . 2.2. Setting up the development environment You must setup your development environment for use with the Eclipse IDE. Note JBoss Tools is deprecated in JBoss EAP 8.0. No enhancements will be made to this feature, and it might be removed in a future release. Procedure Download and install JBoss Tools. For instructions, see Installation Methods in the JBoss Tools Installation guide. Set up the JBoss EAP server in JBoss Tools. For instructions, see How To: Configure the IDE for use with JBoss EAP and JBoss Web Framework Kit in the JBoss Tools guide. Additional resources For more information about tested JBoss Tools versions, see Red Hat JBoss Enterprise Application Platform (EAP) and JBoss Tools . 2.3. Using the quickstart example The quickstart examples provided with JBoss EAP are Maven projects. 2.3.1. About Maven Apache Maven is a distributed build automation tool used in Java application development to create, manage, and build software projects. Maven uses standard configuration files called Project Object Model (POM) files to define projects and manage the build process. POMs describe the module and component dependencies, build order, and targets for the resulting project packaging and output using an XML file. This ensures that the project is built in a correct and uniform manner. Maven achieves this by using a repository. A Maven repository stores Java libraries, plug-ins, and other build artifacts. The default public repository is the Maven 2 Central Repository , but repositories can be private and internal within a company with a goal to share common artifacts among development teams. Repositories are also available from third-parties. For more information, see the Apache Maven project and the Introduction to Repositories guide. Jakarta EE developers typically use to build applications on JBoss EAP. 2.3.2. Using Maven with the quickstarts The artifacts and dependencies needed to build and deploy applications to JBoss EAP 8.0 are hosted on a public repository. Starting with the JBoss EAP 7 quickstarts, it is no longer necessary to configure your Maven settings.xml file to use these repositories when building the quickstarts. The Maven repositories are now configured in the quickstart project POM files. This method of configuration is provided to make it easier to get started with the quickstarts, however, is generally not recommended for production projects because it can slow down your build. JBoss Tools includes Maven, so there is no need to download and install it separately. If you plan to use the Maven command line to build and deploy your applications, then you must first download Maven from the Apache Maven project and install it using the instructions provided in the Maven documentation. Note JBoss Tools is deprecated in JBoss EAP 8.0. No enhancements will be made to this feature, and it might be removed in a future release. 2.4. Download and run the quickstarts 2.4.1. Download the quickstarts JBoss EAP comes with a comprehensive set of quickstart code examples designed to help users begin writing applications using various Jakarta EE technologies. The quickstarts can be downloaded from the Red Hat Customer Portal. Procedure Log in to the JBoss EAP download page on the Red Hat Customer Portal. Select 8.0 in the Version drop-down menu. Find the Red Hat JBoss Enterprise Application Platform 8.0.0 Quickstarts entry in the list and click Download to download a .zip file containing the quickstarts. Save the .zip file to the desired directory. Extract the .zip file. 2.4.2. Import a quickstart into JBoss Tools Once the quickstarts have been downloaded, they can be imported into JBoss Tools and deployed to JBoss EAP. Note JBoss Tools is deprecated in JBoss EAP 8.0. No enhancements will be made to this feature, and it might be removed in a future release. Each quickstart ships with a POM file that contains its project and configuration information. Use this POM file to easily import the quickstart into JBoss Tools. Important If your quickstart project folder is located within the IDE workspace when you import it into JBoss Tools, the IDE generates an invalid project name and WAR archive name. Be sure your quickstart project folder is located outside the IDE workspace before you begin. Procedure Start JBoss Tools. Select File Import . Choose Maven Existing Maven Projects , then click . Figure 2.1. Import Existing Maven Projects Browse to the desired quickstart's directory (for example the helloworld quickstart), and click OK . The Projects list box is populated with the pom.xml file of the selected quickstart project. Figure 2.2. Select Maven Projects Click Finish . Additional resources For more information about tested JBoss Tools versions, see Red Hat JBoss Enterprise Application Platform (EAP) and JBoss Tools . 2.4.3. Run the helloworld quickstart Running the helloworld quickstart is a simple way to verify that the JBoss EAP server is configured and running correctly. Note JBoss Tools is deprecated in JBoss EAP 8.0. No enhancements will be made to this feature, and it might be removed in a future release. Procedure If you have not yet defined a server, add the JBoss EAP server to JBoss Tools. See How To: Configure the IDE for use with JBoss EAP and JBoss Web Framework Kit in the JBoss Tools guide. Right-click the helloworld project in the Project Explorer tab and select Run As Run on Server . Figure 2.3. Run As - Run on Server *Run on Server* screen capture."/> Select the JBoss EAP 8.0 server from the server list and click . Figure 2.4. Run on Server The helloworld quickstart is already listed to be configured on the server. Click Finish to deploy the quickstart. Figure 2.5. Modify Resources Configured on the Server Verify the results. In the Server tab, the JBoss EAP 8.0 server status changes to Started . The Console tab shows messages detailing the JBoss EAP server start and the helloworld quickstart deployment. The helloworld application is available at http://localhost:8080/helloworld and displays the text Hello World! . 2.4.4. Run the bean-validation quickstart Some quickstarts, such as the bean-validation quickstart, do not provide a user interface layer and instead provide Arquillian tests to demonstrate functionality. Note JBoss Tools is deprecated in JBoss EAP 8.0. No enhancements will be made to this feature, and it might be removed in a future release. Procedure Import the bean-validation quickstart into JBoss Tools. In the Servers tab, right-click on the server and choose Start to start the JBoss EAP server. If you do not see a Servers tab or have not yet defined a server, add the JBoss EAP server to JBoss Tools. See How To: Configure the IDE for use with JBoss EAP and JBoss Web Framework Kit in the JBoss Tools guide. Right-click on the bean-validation project in the Project Explorer tab and select Run As Maven Build . Enter the following in the Goals input field and then click Run . Figure 2.6. Edit Configuration Verify the results. The Console tab shows the results of the bean-validation Arquillian tests: 2.4.5. Run the quickstarts from the command line You can easily build and deploy the quickstarts from the command line using Maven. If you do not yet have Maven installed, see the Apache Maven project to download and install it. A README.md file is provided at the root directory of the quickstarts that contains general information about system requirements, configuring Maven, adding users, and running the quickstarts. Each quickstart also contains its own README.md file that provides the specific instructions and Maven commands to run that quickstart. Procedure Review the README.md file in the root directory of the helloworld quickstart. Start the JBoss EAP server. Navigate to the helloworld quickstart directory. Build and deploy the quickstart using the Maven command provided in the quickstart's README.md file. The helloworld application is now available at http://localhost:8080/helloworld and displays the text Hello World! . 2.5. Review the quickstart examples 2.5.1. Explore the helloworld quickstart The helloworld quickstart shows you how to deploy a simple servlet to JBoss EAP. The business logic is encapsulated in a service, which is provided as a Contexts and Dependency Injection (CDI) bean and injected into the Servlet. This quickstart is a starting point to be sure you have configured and started your server properly. Detailed instructions to build and deploy this quickstart using the command line can be found in the README.html file at the root of the helloworld quickstart directory. This topic shows you how to use JBoss Tools to run the quickstart and assumes you have installed JBoss Tools, configured Maven, and imported and successfully run the helloworld quickstart. Note JBoss Tools is deprecated in JBoss EAP 8.0. No enhancements will be made to this feature, and it might be removed in a future release. 2.5.1.1. Examine the directory structure The code for the helloworld quickstart can be found in the QUICKSTART_HOME /helloworld/ directory. The helloworld quickstart is comprised of a Servlet and a CDI bean. It also contains a beans.xml file in the application's WEB-INF/ directory that has a version number of 1.1 and a bean-discovery-mode of all . This marker file identifies the WAR as a bean archive and tells JBoss EAP to look for beans in this application and to activate the CDI. The src/main/webapp/ directory contains the files for the quickstart. All the configuration files for this example are located in the WEB-INF/ directory within src/main/webapp/ , including the beans.xml file. The src/main/webapp/ directory also includes an index.html file, which uses a simple meta refresh to redirect the user's browser to the Servlet, which is located at http://localhost:8080/helloworld/HelloWorld . The quickstart does not require a web.xml file. 2.5.1.2. Review HelloWorldServlet.java code The package declaration and imports have been excluded from these listings. The complete listing is available in the quickstart source code. Note JBoss Tools is deprecated in JBoss EAP 8.0. No enhancements will be made to this feature, and it might be removed in a future release. Prerequisites Install JBoss Tools. For instructions, see Installation Methods in the JBoss Tools Installation guide. Run the helloworld quickstart. Verify that the helloworld quickstart was successfully deployed to JBoss EAP by opening a web browser and accessing the application at http://localhost:8080/helloworld . Procedure Review the HelloWorldServlet code. The HelloWorldServlet.java file is located in the src/main/java/org/jboss/as/quickstarts/helloworld/ directory. This servlet sends the information to the browser. Example: HelloWorldServlet Class Code 42 @SuppressWarnings("serial") 43 @WebServlet("/HelloWorld") 44 public class HelloWorldServlet extends HttpServlet { 45 46 static String PAGE_HEADER = "<html><head><title>helloworld</title></head><body>"; 47 48 static String PAGE_FOOTER = "</body></html>"; 49 50 @Inject 51 HelloService helloService; 52 53 @Override 54 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 55 resp.setContentType("text/html"); 56 PrintWriter writer = resp.getWriter(); 57 writer.println(PAGE_HEADER); 58 writer.println("<h1>" + helloService.createHelloMessage("World") + "</h1>"); 59 writer.println(PAGE_FOOTER); 60 writer.close(); 61 } 62 63 } 2.5.1.2.1. HelloWorldServlet Details This servlet sends information to your browser. Table 2.1. HelloWorldServlet Details Line Note 43 All you need to do is add the @WebServlet annotation and provide a mapping to a URL used to access the servlet. 46-48 Every web page needs correctly formed HTML. This quickstart uses static Strings to write the minimum header and footer output. 50-51 These lines inject the HelloService CDI bean which generates the actual message. As long as we don't alter the API of HelloService, this approach allows us to alter the implementation of HelloService at a later date without changing the view layer. 58 This line calls into the service to generate the message "Hello World", and write it out to the HTTP request. Review the HelloService code. The HelloService.java file is located in the src/main/java/org/jboss/as/quickstarts/helloworld/ directory. This service simply returns a message. No XML or annotation registration is required. Example: HelloService Class Code public class HelloService { String createHelloMessage(String name) { return "Hello " + name + "!"; } } Additional resources For more information about tested JBoss Tools versions, see Red Hat JBoss Enterprise Application Platform (EAP) and JBoss Tools . 2.5.2. Explore the numberguess quickstart The numberguess quickstart shows you how to create and deploy a simple non-persistant application to JBoss EAP. Information is displayed using a JSF view and business logic is encapsulated in two CDI beans. In the numberguess quickstart, you have ten attempts to guess a number between 1 and 100. After each attempt, you're told whether your guess was too high or too low. The code for the numberguess quickstart can be found in the QUICKSTART_HOME /numberguess/ directory where QUICKSTART_HOME is the directory where you downloaded and unzipped the JBoss EAP quickstarts. The numberguess quickstart is comprised of a number of beans, configuration files, and Facelets (JSF) views, and is packaged as a WAR module. Detailed instructions to build and deploy this quickstart using the command line can be found in the README.html file at the root of the numberguess quickstart directory. The following examples use JBoss Tools to run the quickstart. Note JBoss Tools is deprecated in JBoss EAP 8.0. No enhancements will be made to this feature, and it might be removed in a future release. 2.5.2.1. Examine the numberguess configuration files All the configuration files for this example are located in the QUICKSTART_HOME /numberguess/src/main/webapp/WEB-INF/ directory of the quickstart. Prerequisites Install JBoss Tools. For instructions, see Installation Methods in the JBoss Tools Installation guide. Run the numberguess quickstart. Verify the numberguess quickstart was deployed successfully to JBoss EAP by opening a web browser and accessing the application at this URL: http://localhost:8080/numberguess . Note JBoss Tools is deprecated in JBoss EAP 8.0. No enhancements will be made to this feature, and it might be removed in a future release. Procedure Examine the faces-config.xml file. This quickstart uses the JSF 2.2 version of faces-config.xml filename. A standardized version of Facelets is the default view handler in JSF 2.2 so it requires no configuration. This file consists of only the root element and is simply a marker file to indicate JSF should be enabled in the application. <faces-config version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"> </faces-config> Examine the beans.xml file. The beans.xml file contains a version number of 1.1 and a bean-discovery-mode of all . This file is a marker file that identifies the WAR as a bean archive and tells JBoss EAP to look for beans in this application and to activate the CDI. <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" bean-discovery-mode="all"> </beans> Note This quickstart does not need a web.xml file. Additional resources For more information about tested JBoss Tools versions, see Red Hat JBoss Enterprise Application Platform (EAP) and JBoss Tools . 2.5.2.2. Examine the JSF code JSF uses the .xhtml file extension for source files, but delivers the rendered views with the .jsf extension. The home.xhtml file is located in the src/main/webapp/ directory. Example: JSF Source Code 19<html xmlns="http://www.w3.org/1999/xhtml" 20 xmlns:ui="http://java.sun.com/jsf/facelets" 21 xmlns:h="http://java.sun.com/jsf/html" 22 xmlns:f="http://java.sun.com/jsf/core"> 23 24 <head> 25 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> 26 <title>Numberguess</title> 27 </head> 28 29 <body> 30 <div id="content"> 31 <h1>Guess a number...</h1> 32 <h:form id="numberGuess"> 33 34 <!-- Feedback for the user on their guess --> 35 <div style="color: red"> 36 <h:messages id="messages" globalOnly="false" /> 37 <h:outputText id="Higher" value="Higher!" 38 rendered="#{game.number gt game.guess and game.guess ne 0}" /> 39 <h:outputText id="Lower" value="Lower!" 40 rendered="#{game.number lt game.guess and game.guess ne 0}" /> 41 </div> 42 43 <!-- Instructions for the user --> 44 <div> 45 I'm thinking of a number between <span 46 id="numberGuess:smallest">#{game.smallest}</span> and <span 47 id="numberGuess:biggest">#{game.biggest}</span>. You have 48 #{game.remainingGuesses} guesses remaining. 49 </div> 50 51 <!-- Input box for the users guess, plus a button to submit, and reset --> 52 <!-- These are bound using EL to our CDI beans --> 53 <div> 54 Your guess: 55 <h:inputText id="inputGuess" value="#{game.guess}" 56 required="true" size="3" 57 disabled="#{game.number eq game.guess}" 58 validator="#{game.validateNumberRange}" /> 59 <h:commandButton id="guessButton" value="Guess" 60 action="#{game.check}" 61 disabled="#{game.number eq game.guess}" /> 62 </div> 63 <div> 64 <h:commandButton id="restartButton" value="Reset" 65 action="#{game.reset}" immediate="true" /> 66 </div> 67 </h:form> 68 69 </div> 70 71 <br style="clear: both" /> 72 73 </body> 74</html> The following line numbers correspond to those seen when viewing the file in JBoss Tools. Note JBoss Tools is deprecated in JBoss EAP 8.0. No enhancements will be made to this feature, and it might be removed in a future release. Table 2.2. JSF Details Line Note 36-40 These are the messages which can be sent to the user: "Higher!" and "Lower!" 45-48 As the user guesses, the range of numbers they can guess gets smaller. This sentence changes to make sure they know the number range of a valid guess. 55-58 This input field is bound to a bean property using a value expression. 58 A validator binding is used to make sure the user does not accidentally input a number outside of the range in which they can guess. If the validator was not here, the user might use up a guess on an out of bounds number. 59-61 There must be a way for the user to send their guess to the server. Here we bind to an action method on the bean. 2.5.2.3. Examine the numberguess class files All of the numberguess quickstart source files can be found in the QUICKSTART_HOME /numberguess/src/main/java/org/jboss/as/quickstarts/numberguess/ directory. The package declaration and imports have been excluded from these listings. The complete listing is available in the quickstart source code. Procedure Review the Random.java Qualifier Code A qualifier is used to remove ambiguity between two beans, both of which are eligible for injection based on their type. The @Random qualifier is used for injecting a random number. @Target({ TYPE, METHOD, PARAMETER, FIELD }) @Retention(RUNTIME) @Documented @Qualifier public @interface Random { } Review the MaxNumber.java Qualifier Code The @MaxNumber qualifier is used for injecting the maximum number allowed. @Target({ TYPE, METHOD, PARAMETER, FIELD }) @Retention(RUNTIME) @Documented @Qualifier public @interface MaxNumber { } Review the Generator.java Code The Generator class creates the random number via a producer method, exposing the maximum possible number via the same. This class is application-scoped, so you don't get a different random each time. @SuppressWarnings("serial") @ApplicationScoped public class Generator implements Serializable { private java.util.Random random = new java.util.Random(System.currentTimeMillis()); private int maxNumber = 100; java.util.Random getRandom() { return random; } @Produces @Random int () { // a number between 1 and 100 return getRandom().nextInt(maxNumber - 1) + 1; } @Produces @MaxNumber int getMaxNumber() { return maxNumber; } } Review the Game.java Code The session-scoped Game class is the primary entry point of the application. It is responsible for setting up or resetting the game, capturing and validating the user's guess, and providing feedback to the user with a FacesMessage . It uses the post-construct lifecycle method to initialize the game by retrieving a random number from the @Random Instance<Integer> bean. Notice the @Named annotation in the class. This annotation is only required when you want to make the bean accessible to a JSF view by using Jakarta Expression Language, in this case #{game} . @SuppressWarnings("serial") @Named @SessionScoped public class Game implements Serializable { /** * The number that the user needs to guess */ private int number; /** * The users latest guess */ private int guess; /** * The smallest number guessed so far (so we can track the valid guess range). */ private int smallest; /** * The largest number guessed so far */ private int biggest; /** * The number of guesses remaining */ private int remainingGuesses; /** * The maximum number we should ask them to guess */ @Inject @MaxNumber private int maxNumber; /** * The random number to guess */ @Inject @Random Instance<Integer> randomNumber; public Game() { } public int getNumber() { return number; } public int getGuess() { return guess; } public void setGuess(int guess) { this.guess = guess; } public int getSmallest() { return smallest; } public int getBiggest() { return biggest; } public int getRemainingGuesses() { return remainingGuesses; } /** * Check whether the current guess is correct, and update the biggest/smallest guesses as needed. Give feedback to the user * if they are correct. */ public void check() { if (guess > number) { biggest = guess - 1; } else if (guess < number) { smallest = guess + 1; } else if (guess == number) { FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!")); } remainingGuesses--; } /** * Reset the game, by putting all values back to their defaults, and getting a new random number. We also call this method * when the user starts playing for the first time using {@linkplain PostConstruct @PostConstruct} to set the initial * values. */ @PostConstruct public void reset() { this.smallest = 0; this.guess = 0; this.remainingGuesses = 10; this.biggest = maxNumber; this.number = randomNumber.get(); } /** * A JSF validation method which checks whether the guess is valid. It might not be valid because there are no guesses left, * or because the guess is not in range. * */ public void validateNumberRange(FacesContext context, UIComponent toValidate, Object value) { if (remainingGuesses <= 0) { FacesMessage message = new FacesMessage("No guesses left!"); context.addMessage(toValidate.getClientId(context), message); ((UIInput) toValidate).setValid(false); return; } int input = (Integer) value; if (input < smallest || input > biggest) { ((UIInput) toValidate).setValid(false); FacesMessage message = new FacesMessage("Invalid guess"); context.addMessage(toValidate.getClientId(context), message); } } }

Commands:
WFLYUT0021: Registered web context: /helloworld WFLYSRV0010: Deployed "helloworld.war" (runtime-name : "helloworld.war")
clean verify -Parq-remote
------------------------------------------------------- T E S T S ------------------------------------------------------- Running org.jboss.as.quickstarts.bean_validation.test.MemberValidationTest Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.189 sec Results : Tests run: 5, Failures: 0, Errors: 0, Skipped: 0 [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------
EAP_HOME /bin/standalone.sh
mvn clean install wildfly:deploy
42 @SuppressWarnings("serial") 43 @WebServlet("/HelloWorld") 44 public class HelloWorldServlet extends HttpServlet { 45 46 static String PAGE_HEADER = "<html><head><title>helloworld</title></head><body>"; 47 48 static String PAGE_FOOTER = "</body></html>"; 49 50 @Inject 51 HelloService helloService; 52 53 @Override 54 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 55 resp.setContentType("text/html"); 56 PrintWriter writer = resp.getWriter(); 57 writer.println(PAGE_HEADER); 58 writer.println("<h1>" + helloService.createHelloMessage("World") + "</h1>"); 59 writer.println(PAGE_FOOTER); 60 writer.close(); 61 } 62 63 }
public class HelloService { String createHelloMessage(String name) { return "Hello " + name + "!"; } }
<faces-config version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"> </faces-config>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" bean-discovery-mode="all"> </beans>
19<html xmlns="http://www.w3.org/1999/xhtml" 20 xmlns:ui="http://java.sun.com/jsf/facelets" 21 xmlns:h="http://java.sun.com/jsf/html" 22 xmlns:f="http://java.sun.com/jsf/core"> 23 24 <head> 25 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> 26 <title>Numberguess</title> 27 </head> 28 29 <body> 30 <div id="content"> 31 <h1>Guess a number...</h1> 32 <h:form id="numberGuess"> 33 34 <!-- Feedback for the user on their guess --> 35 <div style="color: red"> 36 <h:messages id="messages" globalOnly="false" /> 37 <h:outputText id="Higher" value="Higher!" 38 rendered="#{game.number gt game.guess and game.guess ne 0}" /> 39 <h:outputText id="Lower" value="Lower!" 40 rendered="#{game.number lt game.guess and game.guess ne 0}" /> 41 </div> 42 43 <!-- Instructions for the user --> 44 <div> 45 I'm thinking of a number between <span 46 id="numberGuess:smallest">#{game.smallest}</span> and <span 47 id="numberGuess:biggest">#{game.biggest}</span>. You have 48 #{game.remainingGuesses} guesses remaining. 49 </div> 50 51 <!-- Input box for the users guess, plus a button to submit, and reset --> 52 <!-- These are bound using EL to our CDI beans --> 53 <div> 54 Your guess: 55 <h:inputText id="inputGuess" value="#{game.guess}" 56 required="true" size="3" 57 disabled="#{game.number eq game.guess}" 58 validator="#{game.validateNumberRange}" /> 59 <h:commandButton id="guessButton" value="Guess" 60 action="#{game.check}" 61 disabled="#{game.number eq game.guess}" /> 62 </div> 63 <div> 64 <h:commandButton id="restartButton" value="Reset" 65 action="#{game.reset}" immediate="true" /> 66 </div> 67 </h:form> 68 69 </div> 70 71 <br style="clear: both" /> 72 73 </body> 74</html>
@Target({ TYPE, METHOD, PARAMETER, FIELD }) @Retention(RUNTIME) @Documented @Qualifier public @interface Random { }
@Target({ TYPE, METHOD, PARAMETER, FIELD }) @Retention(RUNTIME) @Documented @Qualifier public @interface MaxNumber { }
@SuppressWarnings("serial") @ApplicationScoped public class Generator implements Serializable { private java.util.Random random = new java.util.Random(System.currentTimeMillis()); private int maxNumber = 100; java.util.Random getRandom() { return random; } @Produces @Random int next() { // a number between 1 and 100 return getRandom().nextInt(maxNumber - 1) + 1; } @Produces @MaxNumber int getMaxNumber() { return maxNumber; } }
@SuppressWarnings("serial") @Named @SessionScoped public class Game implements Serializable { /** * The number that the user needs to guess */ private int number; /** * The users latest guess */ private int guess; /** * The smallest number guessed so far (so we can track the valid guess range). */ private int smallest; /** * The largest number guessed so far */ private int biggest; /** * The number of guesses remaining */ private int remainingGuesses; /** * The maximum number we should ask them to guess */ @Inject @MaxNumber private int maxNumber; /** * The random number to guess */ @Inject @Random Instance<Integer> randomNumber; public Game() { } public int getNumber() { return number; } public int getGuess() { return guess; } public void setGuess(int guess) { this.guess = guess; } public int getSmallest() { return smallest; } public int getBiggest() { return biggest; } public int getRemainingGuesses() { return remainingGuesses; } /** * Check whether the current guess is correct, and update the biggest/smallest guesses as needed. Give feedback to the user * if they are correct. */ public void check() { if (guess > number) { biggest = guess - 1; } else if (guess < number) { smallest = guess + 1; } else if (guess == number) { FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!")); } remainingGuesses--; } /** * Reset the game, by putting all values back to their defaults, and getting a new random number. We also call this method * when the user starts playing for the first time using {@linkplain PostConstruct @PostConstruct} to set the initial * values. */ @PostConstruct public void reset() { this.smallest = 0; this.guess = 0; this.remainingGuesses = 10; this.biggest = maxNumber; this.number = randomNumber.get(); } /** * A JSF validation method which checks whether the guess is valid. It might not be valid because there are no guesses left, * or because the guess is not in range. * */ public void validateNumberRange(FacesContext context, UIComponent toValidate, Object value) { if (remainingGuesses <= 0) { FacesMessage message = new FacesMessage("No guesses left!"); context.addMessage(toValidate.getClientId(context), message); ((UIInput) toValidate).setValid(false); return; } int input = (Integer) value; if (input < smallest || input > biggest) { ((UIInput) toValidate).setValid(false); FacesMessage message = new FacesMessage("Invalid guess"); context.addMessage(toValidate.getClientId(context), message); } } }