Diving into the Weld examples It's time to pull the covers back and dive into the internals of Weld example applications. Let's start with the simpler of the two examples, weld-numberguess.
The numberguess example in depth In the numberguess application you get 10 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 numberguess example is comprised of a number of beans, configuration files and Facelets (JSF) views, packaged as a war module. Let's start by examining the configuration files. All the configuration files for this example are located in WEB-INF/, which can be found in the src/main/webapp directory of the example. First, we have the JSF 2.0 version of faces-config.xml. A standardized version of Facelets is the default view handler in JSF 2.0, so there's really nothing that we have to configure. Thus, the configuration consists of only the root element. ]]> There's also an empty beans.xml file, which tells the container to look for beans in this application and to activate the CDI services. Finally, there's the familiar web.xml: weld-jsf-numberguess-war Weld JSF numberguess example (war) Faces Servlet javax.faces.webapp.FacesServlet 1 Faces Servlet *.jsf javax.faces.DEFAULT_SUFFIX .xhtml 10 ]]> Enable and initialize the JSF servlet Configure requests for URLs ending in .jsf to be handled by JSF Tell JSF that we will be giving our JSF views (Facelets templates) an extension of .xhtml Configure a session timeout of 10 minutes This demo uses JSF 2 as the view framework, but you can use Weld with any servlet-based web framework, such as JSF 1.2 or Wicket. Let's take a look at the main JSF view, src/main/webapp/home.xhtml.

Guess a number...

I'm thinking of a number between #{game.smallest} and #{game.biggest}. You have #{game.remainingGuesses} guesses remaining.
Your guess:
]]>
Facelets is the built-in templating language for JSF. Here we are wrapping our page in a template which defines the layout. There are a number of messages which can be sent to the user, "Higher!", "Lower!" and "Correct!" 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. This input field is bound to a bean property using a value expression. A validator binding is used to make sure the user doesn't accidentally input a number outside of the range in which they can guess - if the validator wasn't here, the user might use up a guess on an out of bounds number. And, of course, 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.
The example exists of 4 classes, the first two of which are qualifiers. First, there is the @Random qualifier, used for injecting a random number: There is also the @MaxNumber qualifier, used for injecting the maximum number that can be injected: The application-scoped Generator class is responsible for creating the random number, via a producer method. It also exposes the maximum possible number via a producer method: The Generator is application scoped, so we don't get a different random each time. The package declaration and imports have been excluded from these listings. The complete listing is available in the example source code. The final bean in the application is the session-scoped Game class. This is the primary entry point of the application. It's responsible for setting up or resetting the game, capturing and validating the user's guess and providing feedback to the user with a FacesMessage. We've used the post-construct lifecycle method to initialize the game by retrieving a random number from the @Random Instance<Integer> bean. You'll notice that we've also added the @Named annotation to this class. This annotation is only required when you want to make the bean accessible to a JSF view via EL (i.e., #{game}). randomNumber; public Game() {} 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--; } @PostConstruct public void reset() { this.smallest = 0; this.guess = 0; this.remainingGuesses = 10; this.biggest = maxNumber; this.number = randomNumber.get(); } 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); } } 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; } }]]>
The numberguess example in Apache Tomcat or Jetty A couple of modifications must be made to the numberguess artifact in order to deploy it to Tomcat or Jetty. First, Weld must be deployed as a Web Application library under WEB-INF/lib since the servlet container does not provide the CDI services. For your convenience we provide a single jar suitable for running Weld in any servlet container (including Jetty), weld-servlet.jar. You must also include the jars for JSF, EL, and the common annotations (jsr250-api.jar), all of which are provided by the Java EE platform (a Java EE application server). Are you starting to appreciate why a Java EE platform is worth using? Second, we need to explicitly specify the servlet listener in web.xml, again because the container isn't doing this stuff for you. The servlet listener boots Weld and controls it's interaction with requests. org.jboss.weld.environment.servlet.Listener ]]> When Weld boots, it places the javax.enterprise.inject.spi.BeanManager, the portable SPI for obtaining bean instances, in the ServletContext under a variable name equal to the fully-qualified interface name. You generally don't need to access this interface, but Weld makes use of it.
The numberguess example for Apache Wicket Weld includes a number of portable extensions for JSR-299, including an extension for Wicket, which allows you to inject beans into Wicket components and leverage the conversation context. In this section, we'll walk you through the Wicket version of the numberguess example. You may want to review the Wicket documentation at http://wicket.apache.org/ before reading this section, if you aren't already familiar with the framework. Wicket is another environment that relies on the Weld servlet extension. The use of Jetty is common in the Wicket community, and is thus chosen here as the runtime container. You've seen already that Jetty is perfectly capable of running CDI applications with Weld add-ons, and this environment is no different. We'll also be using the Eclipse IDE in these examples. Instructions are provided later for running the example from the command line, but since you'll likely need to do more than just deploy examples, we'll get setup in this full development environment.
Creating the Eclipse project To use the Wicket example in Eclipse, you have one of two choices. You can either use a Maven plugin to generate a regular Eclipse Web project, or you can open the example natively using the m2eclipse plugin. Since the Weld source code relies so heavily on Maven, we encourage you to bite the bullet and adopt the m2eclipse plugin. Both approaches are described here for your convenience.. If you have m2eclipse installed, you can open any Maven project directly. From within Eclipse, select File -> Import... -> Maven Projects. Then, browse to the location of the Wicket numberguess example. You should see that Eclipse recognizes the existence of a Maven project. This will create a project in your workspace called weld-wicket-numberguess. You'll notice after importing, the project has a build error. That's because we need to enable a Maven profile. Right-click on the project and select Properties, then select the Maven tab in the window that appears. In the form field labeled "Active Maven Profiles (comma separated):", type jetty. That will enable some extra dependencies that allow the project to compile. Additionally, uncheck the box labeled "Skip Maven compile plugin when processing resources (recommended)". That solves an incompatiblity between the m2eclipse plugin and the Maven enforcer plugin that we use for the Weld project. Now, you're ready to develop! Be sure to uncheck the box "Skip Maven compile plugin when processing resources (recommended)" in the Maven properties screen or else the example might not run in Eclipse because beans.xml will be missing from the classpath! See the MNGECLIPSE-768 issue report for details. If you are not using the m2eclipse plugin, you have to follow different steps to import the project. First, switch into the Wicket numberguess example, then execute the Maven Eclipse plugin with the jetty profile activated, as follows: cd examples/wicket/numberguess mvn -Pjetty eclipse:eclipse]]> Then, from Eclipse, choose File -> Import... -> General -> Existing Projects into Workspace, select the root directory of the numberguess example, and click Finish. This will create a project in your workspace called weld-wicket-numberguess. It's time to get the example running!
Running the example from Eclipse This project follows the wicket-quickstart approach of creating an instance of Jetty in the Start class. So running the example is as simple as right-clicking on that Start class in src/test/java in the Package Explorer and choosing Run as Java Application. You should see console output related to Jetty starting up; then visit able http://localhost:9090 to view the app. To debug choose Debug as Java Application instead.
Running the example from the command line in JBoss AS or Tomcat This example can also be deployed from the command line in a (similar to the other examples). Assuming you have set up the local.build.properties file in the examples directory to specify the location of JBoss AS or Tomcat, as previously described, you can run: ant deploy]]> to deploy the example to JBoss AS, and: ant tomcat.deploy]]> to deploy the example to Tomcat. You can then access application at http://localhost:8080/weld-numberguess-wicket. Alternatively, you can run the application in place on an embedded Jetty container using the following Maven command: mvn jetty:run -Pjetty]]> Enough toying with deployment, let's dive into the code.
Understanding the code The code in the wicket numberguess example is very similar to the JSF-based numberguess example. The business layer is identical! Where things differ is in view binding. JSF uses Unified EL expressions to bind XML-based view layer components in JSF views to beans. In contrast, Wicket defines its components in Java. These Java-based view components have a one-to-one mapping with HTML elements in an adjacent (pure) HTML file. All view logic, including binding of components to models and controlling the response of view actions, is handled in Java. The integration of Weld with Wicket takes advantage of the same qualifier annotations used in your business layer to provide injection into your WebPage subclass (or into other custom Wicket component subclasses). Here's where things differ from the JSF numberguess example: Each wicket application must have a WeldApplication subclass. In our case, our application class is NumberGuessApplication: This class specifies which page Wicket should treat as our home page, in our case, HomePage.class In HomePage, we see typical Wicket code to set up page elements. The bit that is interesting is the injection of the Game bean: The Game bean is can then be used, for example, by the code for submitting a guess: game.getGuess()) { info("Higher!"); } else if (game.getNumber() < game.getGuess()) { info("Lower"); } target.addComponent(form); } }; ]]> All injections may be serialized; actual storage of the bean is managed by JSR-299. Note that Wicket components, like the HomePage and it subcomponents, are not JSR-299 beans. Wicket components allow injection, but they cannot use interceptors, decorators or lifecycle callbacks such as @PostConstruct or methods. The components would need to delegate to actual beans to leverage these features. The example uses AJAX for processing of button events, and dynamically hides buttons that are no longer relevant, for example when the user has won the game. In order to activate Wicket for this webapp, the Wicket filter is added to web.xml, and our application class is specified in web.xml: Wicket Filter org.apache.wicket.protocol.http.WicketFilter applicationClassName org.jboss.weld.examples.wicket.NumberGuessApplication Wicket Filter /* ]]> The servlet listener is still required, as in the Tomcat example, to bootstrap CDI when Jetty starts and to hook CDI into the Jetty servlet request and session lifecycles. However, rather than putting it into the web.xml, it is placed into an override file, src/main/webapp/WEB-INF/jetty-additions-to-web.xml, that is passed to Jetty as an extra descriptor to be appended to the web.xml configuration. org.jboss.weld.environment.servlet.Listener ]]>
The numberguess example for Java SE with Swing This example shows how to use the Weld SE extension to in a Java SE based Swing application with no EJB or servlet dependencies. This example can be found in the examples/se/numberguess folder of the Weld distribution. To run the example: Ensure that Maven 2 (version 2.0.10+) is installed and in your PATH Ensure that the JAVA_HOME environment variable is pointing to your JDK installation Open a command line or terminal window in the examples/se/numberguess directory Execute the following command mvn -Drun Let's have a look at the significant code and configuration files that make up this example. As usual, there is an empty beans.xml file in the root package (src/main/resources/beans.xml), which marks this application as a CDI application. The game's main logic is located in Game.java. Here is the code for that class, highlighting the ways in which this differs from the web application version: 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.guess = 0; this.remainingGuesses = 10; this.biggest = maxNumber; this.number = rndGenerator.next(); } }]]> The bean is application scoped rather than session scoped, since an instance of a Swing application typically represents a single 'session'. Notice that the bean is not named, since it doesn't need to be accessed via EL. In Java SE there is no JSF FacesContext to which messages can be added. Instead the Game class provides additional information about the state of the current game including: If the game has been won or lost If the most recent guess was invalid This allows the Swing UI to query the state of the game, which it does indirectly via a class called MessageGenerator, in order to determine the appropriate messages to display to the user during the game. Since there is no dedicated validation phase, validation of user input is performed during the check() method. The reset() method makes a call to the injected rndGenerator in order to get the random number at the start of each game. Note that it can't use Instance.get() like the JSF example does because there will not be any active contexts like there are during a JSF request. The MessageGenerator class depends on the current instance of Game 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 MessageGenerator is as follows: The instance of Game for the application is injected here. The Game's state is interrogated to determine the appropriate challenge message ... ... and again to determine whether to congratulate, console or encourage the user to continue. Finally we come to the NumberGuessFrame class which provides the Swing front end to our guessing game. The injected instance of the game (logic and state). The injected message generator for UI messages. This application is started in the prescribed Weld SE way, by observing the ContainerInitialized event. This method initializes all of the Swing components. Note the use of the msgGenerator here. guessButtonActionPerformed is called when the 'Guess' button is clicked, and it does the following: Gets the guess entered by the user and sets it as the current guess in the Game Calls game.check() to validate and perform one 'turn' of the game Calls refreshUI. If there were validation errors with the input, this will have been captured during game.check() and as such will be reflected in the messages returned by MessageGenerator 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). replayBtnActionPerformed simply calls game.reset() to start a new game and refreshes the messages in the UI.
The translator example in depth The translator example will take any sentences you enter, and translate them to Latin. (Well, not really, but the stub is there for you to implement, at least. Good luck!) The translator example is built as an ear and contains EJBs. As a result, it's structure is more complex than the numberguess example. Java EE 6, which bundles EJB 3.1, allows you to package EJBs in a war, which will make this structure much simpler! Still, there are other advantages of using an ear. First, let's take a look at the ear aggregator, which is located in the example's ear directory. Maven automatically generates the application.xml for us from this plugin configuration: org.apache.maven.plugins maven-ear-plugin org.jboss.weld.examples.jsf.translator weld-jsf-translator-war /weld-translator ]]> This configuration overrides the web context path, resulting in this application URL: http://localhost:8080/weld-translator. If you weren't using Maven to generate these files, you would need META-INF/application.xml: weld-jsf-translator-ear The Weld JSF translator example (ear) weld-translator.war /weld-translator weld-translator.jar ]]> Next, lets look at the war, which is located in the example's war directory. Just as in the numberguess example, we have a faces-config.xml for JSF 2.0 and a web.xml (to activate JSF) under WEB-INF, both sourced from src/main/webapp/WEB-INF. More interesting is the JSF view used to translate text. Just as in the numberguess example we have a template, which surrounds the form (ommitted here for brevity):
Your text Translation
]]>
The user can enter some text in the left-hand textarea, and hit the translate button to see the result to the right. Finally, let's look at the EJB module, which is located in the example's ejb directory. In src/main/resources/META-INF there is just an empty beans.xml, used to mark the archive as containing beans. We've saved the most interesting bit to last, the code! The project has two simple beans, SentenceParser and TextTranslator and two session beans, TranslatorControllerBean and SentenceTranslator. You should be getting quite familiar with what a bean looks like by now, so we'll just highlight the most interesting bits here. Both SentenceParser and TextTranslator are dependent beans, and TextTranslator uses constructor injection: TextTranslator uses the simple bean (really just a plain Java class!) SentenceParser to parse the sentence and then calls on the stateless bean with the local business interface Translator to perform the translation. That's where the magic happens. Of course, we couldn't develop a full translator, but it's convincing enough to anyone who doesn't understand Latin! Finally, there is UI orientated controller. This is a request scoped, named, stateful session bean, which injects the translator. It collects the text from the user and dispatches it to the translator. The bean also has getters and setters for all the fields on the page.
That concludes our short tour of the Weld starter examples. For more information on Weld, please visit http://www.seamframework.org/Weld.