Weld - JSR-299 Reference Implementation

JSR-299: The new Java standard for dependency injection and contextual lifecycle management

Nicola Benaglia

Italian Translation

Spanish Translation

Eun-Ju Ki,

Korean Translation

Francesco Milesi

Italian Translation

A note about naming and nomenclature
I. Beans
1. Introduction
1.1. What is a bean?
1.2. Getting our feet wet
2.1. The anatomy of a bean
2.1.1. Bean types, qualifiers and dependency injection
2.1.2. Scope
2.1.3. EL name
2.1.4. Alternatives
2.1.5. Interceptor binding types
2.2. What kinds of classes are beans?
2.2.1. Managed beans
2.2.2. Session beans
2.2.3. Producer methods
2.2.4. Producer fields
3. JSF web application example
4. Dependency injection and programmatic lookup
4.1. Injection points
4.2. What gets injected
4.3. Qualifier annotations
4.4. Qualifiers with members
4.5. Multiple qualifiers
4.6. Alternatives
4.7. Fixing unsatisfied and ambiguous dependencies
4.8. Client proxies
4.9. Obtaining a contextual instance by programmatic lookup
4.10. The InjectionPoint object
5. Scopes and contexts
5.1. Scope types
5.2. Built-in scopes
5.3. The conversation scope
5.3.1. Conversation demarcation
5.3.2. Conversation propagation
5.3.3. Conversation timeout
5.4. The dependent pseudo-scope
5.5. The @New qualifier
II. Weld, the CDI Reference Implementation
6. Getting started with Weld
6.1. Prerequisites
6.2. Deploying to JBoss AS
6.3. Deploying to GlassFish
6.4. Deploying to Apache Tomcat
6.4.1. Deploying with Ant
6.4.2. Deploying with Maven
6.5. Deploying to Jetty
7. Diving into the Weld examples
7.1. The numberguess example in depth
7.1.1. The numberguess example in Apache Tomcat or Jetty
7.2. The numberguess example for Apache Wicket
7.2.1. Creating the Eclipse project
7.2.2. Running the example from Eclipse
7.2.3. Running the example from the command line in JBoss AS or Tomcat
7.2.4. Understanding the code
7.3. The numberguess example for Java SE with Swing
7.4. The translator example in depth
III. Loose coupling with strong typing
8. Producer methods
8.1. Scope of a producer method
8.2. Injection into producer methods
8.3. Use of @New with producer methods
8.4. Disposer methods
9. Interceptors
9.1. Interceptor bindings
9.2. Implementing interceptors
9.3. Enabling interceptors
9.4. Interceptor bindings with members
9.5. Multiple interceptor binding annotations
9.6. Interceptor binding type inheritance
9.7. Use of @Interceptors
10. Decorators
10.1. Delegate object
10.2. Enabling decorators
11. Events
11.2. Event observers
11.3. Event producers
11.4. Conditional observer methods
11.5. Event qualifiers with members
11.6. Multiple event qualifiers
11.7. Transactional observers
12. Stereotypes
12.1. Default scope for a stereotype
12.2. Interceptor bindings for stereotypes
12.3. Name defaulting with stereotypes
12.4. Alternative stereotypes
12.5. Stereotype stacking
12.6. Built-in stereotypes
13. Specialization, inheritance and alternatives
13.1. Using alternative stereotypes
13.2. A minor problem with alternatives
13.3. Using specialization
14. Java EE component environment resources
14.1. Defining a resource
14.2. Typesafe resource injection
IV. CDI and the Java EE ecosystem
15. Java EE integration
15.1. Built-in beans
15.2. Injecting Java EE resources into a bean
15.3. Calling a bean from a servlet
15.4. Calling a bean from a message-driven bean
15.5. JMS endpoints
15.6. Packaging and deployment
16. Portable extensions
16.1. The BeanManager object
16.2. The Bean interface
16.3. The Context interface
17. Next steps
V. Weld reference
18. Application servers and environments supported by Weld
18.1. Using Weld with JBoss AS
18.2. GlassFish
18.3. Servlet containers (such as Tomcat or Jetty)
18.3.1. Tomcat
18.3.2. Jetty
18.4. Java SE
18.4.1. CDI SE Module
19. CDI extensions available as part of Weld
19.1. Weld Logger
20. Alternative view layers
20.1. Wicket CDI integration
20.1.1. The WebApplication class
20.1.2. Conversations with Wicket
A. Integrating Weld into other environments
A.1. The Weld SPI
A.1.1. Deployment structure
A.1.2. EJB descriptors
A.1.3. EE resource injection and resolution services
A.1.4. EJB services
A.1.5. JPA services
A.1.6. Transaction Services
A.1.7. Resource Services
A.1.8. Injection Services
A.1.9. Security Services
A.1.10. Bean Validation Services
A.1.11. Identifying the BDA being addressed
A.1.12. The bean store
A.1.13. The application context
A.1.14. Initialization and shutdown
A.2. The contract with the container

Part I. Beans

The JSR-299 specification (CDI) defines a set of complementary services that help improve the structure of application code. CDI layers an enhanced lifecycle and interaction model over existing Java component types, including managed beans and Enterprise Java Beans. The CDI services provide:

• an improved lifecycle for stateful objects, bound to well-defined contexts,

• a typesafe approach to dependency injection,

• object interaction via an event notification facility,

• a better approach to binding interceptors to objects, along with a new kind of interceptor, called a decorator, that is more appropriate for use in solving business problems, and

• an SPI for developing portable extensions to the container.

The CDI services are a core aspect of the Java EE platform and include full support for Java EE modularity and the Java EE component architecture. But the specification does not limit the use of CDI to the Java EE environment. In the Java SE environment, the services might be provided by a standalone CDI implementation like Weld (see Section 18.4.1, “CDI SE Module”), or even by a container that also implements the subset of EJB defined for embedded usage by the EJB 3.1 specification. CDI is especially useful in the context of web application development, but the problems it solves are general development concerns and it is therefore applicable to a wide variety of application.

An object bound to a lifecycle context is called a bean. CDI includes built-in support for several different kinds of bean, including the following Java EE component types:

• managed beans, and

• EJB session beans.

Both managed beans and EJB session beans may inject other beans. But some other objects, which are not themselves beans in the sense used here, may also have beans injected via CDI. In the Java EE platform, the following kinds of component may have beans injected:

• message-driven beans,

• interceptors,

• servlets, servlet filters and servlet event listeners,

• JAX-WS service endpoints and handlers, and

• JSP tag handlers and tag library event listeners.

CDI relieves the user of an unfamiliar API of the need to answer the following questions:

• What is the lifecycle of this object?

• How many simultaneous clients can it have?

• Do I need to explicitly destroy it?

• Where should I keep the reference to it when I'm not currently using it?

• How can I define an alternative implementation, so that the implementation can vary at deployment time?

• How should I go about sharing this object between other objects?

CDI is more than a framework. It's a whole, rich programming model. The theme of CDI is loose-coupling with strong typing. Let's study what that phrase means.

A bean specifies only the type and semantics of other beans it depends upon. It need not be aware of the actual lifecycle, concrete implementation, threading model or other clients of any bean it interacts with. Even better, the concrete implementation, lifecycle and threading model of a bean may vary according to the deployment scenario, without affecting any client. This loose-coupling makes your code easier to maintain.

Events, interceptors and decorators enhance the loose-coupling inherent in this model:

• event notifications decouple event producers from event consumers,

• interceptors decouple technical concerns from business logic, and

• decorators allow business concerns to be compartmentalized.

What's even more powerful (and comforting) is that CDI provides all these facilities in a typesafe way. CDI never relies on string-based identifiers to determine how collaborating objects fit together. Instead, CDI uses the typing information that is already available in the Java object model, augmented using a new programming pattern, called qualifier annotations, to wire together beans, their dependencies, their interceptors and decorators, and their event consumers. Usage of XML descriptors is minimized to truly deployment-specific information.

But CDI isn't a restrictive programming model. It doesn't tell you how you should to structure your application into layers, how you should handle persistence, or what web framework you have to use. You'll have to decide those kinds of things for yourself.

CDI even provides a comprehensive SPI, allowing other kinds of object defined by future Java EE specifications or by third-party frameworks to be cleanly integrated with CDI, take advantage of the CDI services, and interact with any other kind of bean.

CDI was influenced by a number of existing Java frameworks, including Seam, Guice and Spring. However, CDI has its own, very distinct, character: more typesafe than Seam, more stateful and less XML-centric than Spring, more web and enterprise-application capable than Guice. But it couldn't have been any of these without inspiration from the frameworks mentioned and lots of collaboration and hard work by the JSR-299 Expert Group (EG).

Finally, CDI is a Java Community Process (JCP) standard. Java EE 6 requires that all compliant application servers provide support for JSR-299 (even in the web profile).

Part II. Weld, the CDI Reference Implementation

Weld, the JSR-299 Reference Implementation (RI), is being developed as part of the Seam project. You can download the latest community release of Weld from the download page. Information about the Weld source code repository and instructions about how to obtain and build the source can be found on the same page.

Weld provides a complete SPI allowing Java EE containers such as JBoss AS and GlassFish to use Weld as their built-in CDI implementation. Weld also runs in servlet engines like Tomcat and Jetty, or even in a plain Java SE environment.

Weld comes with an extensive library of examples, which are a great starting point from which to learn CDI.

Chapter 6. Getting started with Weld

Weld comes with two starter example applications, in addition to more specialized examples. The first, weld-numberguess, is a web (WAR) example containing only non-transactional managed beans. This example can be run on a wide range of servers, including JBoss AS, GlassFish, Apache Tomcat, Jetty, Google App Engine, and any compliant Java EE 6 container. The second example, weld-translator, is an enterprise (EAR) example that contains session beans. This example must be run on JBoss AS 5.2, Glassfish 3.0 or any compliant Java EE 6 container.

Both examples use JSF 2.0 as the web framework and, as such, can be found in the examples/jsf directory of the Weld distribution.

6.2. Deploying to JBoss AS

To deploy the examples to JBoss AS, you'll need JBoss AS 5.2.0.Beta1 or above. If a release of the JBoss AS 5.2 line isn't yet available, you can download a nightly snapshot. The reason JBoss AS 5.2.0.Beta1 or above is required is because it's the first release that has both CDI and Bean Validation support built-in, making it close enough to Java EE 6 to run the examples. The good news is that there are no additional modifications you have to make to the server. It's ready to go!

After you have downloaded JBoss AS, extract it. (We recommended renaming the folder to include the as qualifier so it's clear that it's the application server). You can move the extracted folder anywhere you like. Wherever it lays to rest, that's what we'll call the JBoss AS installation directory, or JBOSS_HOME.

$> unzip jboss-5.2.*.zip$> mv jboss-5.2.*/ jboss-as-5.2

In order for the build scripts to know where to deploy the example, you have to tell them where to find your JBoss AS installation (i.e., JBOSS_HOME). Create a new file namedlocal.build.properties in the examples directory of the Weld distribution and assign the path of your JBoss AS installation to the property key jboss.home, as follows:

jboss.home=/path/to/jboss-as-5.2

Switch to the examples/jsf/numberguess directory and execute the Ant deploy target:

$> cd examples/jsf/numberguess$> ant deploy

If you haven't already, start JBoss AS. You can either start JBoss AS from a Linux shell:

$> cd /path/to/jboss-as-5.2$> ./bin/run.sh

a Windows command window:

$> cd c:\path\to\jboss-as-5.2\bin$> run

or you can start the server using an IDE, like Eclipse.

Note

If you are using Eclipse, you should seriously consider installing the JBoss Tools add-ons, which include a wide variety of tooling for JSR-299 and Java EE development, as well as an enhanced JBoss AS server view.

Wait a few seconds for the application to deploy (or the application server to start) and see if you can determine the most efficient approach to pinpoint the random number at the local URL http://localhost:8080/weld-numberguess.

Tip

The Ant build script includes additional targets for JBoss AS to deploy and undeploy the archive in either exploded or packaged format and to tidy things up.

• ant restart - deploy the example in exploded format to JBoss AS

• ant explode - update an exploded example, without restarting the deployment

• ant deploy - deploy the example in compressed jar format to JBoss AS

• ant undeploy - remove the example from JBoss AS

• ant clean - clean the example

The second starter example, weld-translator, will translate your text into Latin. (Well, not really, but the stub is there for you to implement, at least. Good luck!) To try it out, switch to the translator example directory and execute the deploy target:

$> cd examples/jsf/translator$> ant deploy

Note

The translator uses session beans, which are packaged in an EJB module within an EAR. Java EE 6 will allow session beans to be deployed in WAR modules, but that's a topic for a later chapter.

Again, wait a few seconds for the application to deploy (if you're really bored, read the log messages), and visit http://localhost:8080/weld-translator to begin pseudo-translating.

TODO Insert note about upgrading the Weld deployer that directs reader to section on the JBoss AS environment

6.3. Deploying to GlassFish

Deploying to GlassFish should be easy, right? After all, it's the Java EE 6 reference implementation. Since it's the Java EE 6 reference implementation, that means it also bundles the JSR-299 reference implementation, Weld! So yes, it's very easy.

To deploy the examples to GlassFish, you'll need the final GlassFish V3 release (the preview release won't do). If the final release isn't yet available, you can download a promoted build in the meantime. Select the b69 preview release or above that ends in either -unix.sh or -windows.exe depending on your platform. After the download is complete, execute the installer. On Linux/Unix, you'll need to first make the script executable.

$> chmod 755 glassfish-v3-b69-unix.sh$> ./glassfish-v3-b69-unix.sh

On Windows you can just click on the executable. Follow the instructions in the installer. It will create a single domain named domain1. You'll use that domain to deploy the example. We recommend that you choose 7070 as the main HTTP port to avoid conflicts with a running instance of JBoss AS (or Apache Tomcat).

If you've deployed either of the starter examples, weld-numberguess or weld-translator, to JBoss AS, then you already have the deployable artifact you need. If not, switch to either of the two directories and build it.

$> cd examples/jsf/numberguess (or examples/jsf/translator)$> ant package

The deployable archive for the weld-numberguess, named weld-numberguess.war, ends up in the example's target directory. The archive for the weld-translator example, named weld-translator.ear, ends up in the example's ear/target directory. All you need to do now is deploy them to GlassFish.

You deploy applications to GlassFish using the GlassFish Admin Console. To get the Admin Console running, you need to start a GlassFish domain, in our case domain1. Switch to the bin folder in the directory where you installed GlassFish and execute the following command:

$> asadmin start-domain domain1 After a few seconds you can visit the Admin Console in the browser at the URL http://localhost:4848. In the tree on the left-hand side of the page, click on "Applications", then click on the "Deploy..." button under the heading "Applications" and select the deployable artifact for either of the two examples. The deployer should recognize that you have selected a Java EE artifact and allow you to start it. You can see the examples running at either http://localhost:7070/weld-numberguess or http://localhost:7070/weld-translator, depending on which example you deployed. The reason the same artifact can be deployed to both JBoss AS and GlassFish, without any modifications, is because all of the features being used are part of the standard platform. And what a capable platform it has become! 6.5. Deploying to Jetty Support for Jetty in the examples is a more recent addition. Since Jetty is traditionally used with Maven, there are no Ant targets. You must invoke the Maven build directly to deploy the examples to Jetty out of the box. Also, only the weld-numberguess example is configured for Jetty support at the time of writing. If you've read through the entire Tomcat section, then you're all ready to go. The Maven build parallels the embedded Tomcat deployment. If not, don't worry. We'll still go over everything that you need to know again in this section. The Maven POM (pom.xml) includes a profile named jetty that activates the Maven Jetty plugin, which you can use to start Jetty in embedded mode and deploy the application in place. You don't need anything else installed except to have the Maven command (mvn) on your path. The rest will be downloaded from the internet when the build is run. To run the weld-numberguess example on Jetty, switch to the example directory and execute the inplace goal of the Maven WAR plugin followed by the run goal of the Maven Jetty plugin with the jetty profile enabled, as follows:$> cd examples/jsf/numberguess
$> mvn war:inplace jetty:run -Pjetty The log output of Jetty will be shown in the console. Once Jetty reports that the application has deployed, you can access it at the following local URL: http://localhost:9090/weld-numberguess. The port is defined in the Maven Jetty plugin configuration within the jetty profile. Any changes to assets in src/main/webapp take effect immediately. If a change to a webapp configuration file is made, the application may automatically redeploy. The redeploy behavior can be fined-tuned in the plugin configuration. If you make a change to a classpath resource, you need to execute a build and the inplace goal of the Maven WAR plugin, again with the jetty profile enabled.$> mvn compile war:inplace -Pjetty

The war:inplace goal copies the compiled classes and JARs inside src/main/webapp, under WEB-INF/classes and WEB-INF/lib, respectively, mixing source and compiled files. However, the build does work around these temporary files by excluding them from the packaged WAR and cleaning them during the Maven clean phase.

You have two options if you want to run the example on Jetty from the IDE. You can either install the m2eclispe[link] plugin and run the goals as described above. Your other option is to start the Jetty container from a Java application.

First, initialize the Eclipse project:

$> mvn clean eclipse:clean eclipse:eclipse -Pjetty-ide Next, assemble all the necessary resources under src/main/webapp:$> mvn war:inplace -Pjetty-ide

Now, you are ready to run the server in Eclipse. Import the project into your Eclipse workspace using "Import Existing Project into Workspace. Then, find the start class in src/jetty/java and run its main method as a Java Application. Jetty will launch. You can view the application at the following local URL: http://localhost:8080. Pay particular attention to the port in the URL and the lack of a trailing context path.

Now that you have gotten the starter applications deployed on the server of your choice, you probably want to know a little bit about how they actually work.

Chapter 7. 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.

7.2. 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.

Tip

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.

Note

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.

7.2.1. 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. You're now ready to develop!

Note

You are also advised to uncheck the box "Skip Maven compiler when processing resources" in the Maven properties screen because of conflicts with the Maven enforcer plugin.

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!

7.3. 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:

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:

@ApplicationScoped

public class Game implements Serializable
{
public static final int MAX_NUM_GUESSES = 10;
private Integer number;
private int guess = 0;
private int smallest = 0;
@Inject
@MaxNumber
private int maxNumber;
private int biggest;
private int remainingGuesses = MAX_NUM_GUESSES;
private boolean validNumberRange = true;
@Inject
Generator rndGenerator;
public Game()
{
}
...
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.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 cannot use manager.getInstanceByType(Integer.class, new AnnotationLiteral(){}) as the JSF example does because there will not be any active contexts like there is 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:

public class MessageGenerator

{
@Inject
private 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 guessed 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.";
}
}
}
 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.

public class NumberGuessFrame extends javax.swing.JFrame

{
@Inject
private Game game;
@Inject
private MessageGenerator msgGenerator;
public void start(@Observes ContainerInitialized event)
{
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());
messageLabel.setText(msgGenerator.getResultMessage());
...
}
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;
}
 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.

7.4. 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.

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:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
<modules>
<webModule>
<groupId>org.jboss.weld.examples.jsf.translator</groupId>
<artifactId>weld-jsf-translator-war</artifactId>
<contextRoot>/weld-translator</contextRoot>
</webModule>
</modules>
</configuration>
</plugin>

Tip

If you weren't using Maven to generate these files, you would need META-INF/application.xml:

<application version="5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/application_5.xsd">

<display-name>weld-jsf-translator-ear</display-name>
<description>The Weld JSF translator example (EAR)</description>

<module>
<web>
<web-uri>weld-translator.war</web-uri>
<context-root>/weld-translator</context-root>
</web>
</module>
<module>
<ejb>weld-translator.jar</ejb>
</module>
</application>

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):

<h:form id="translator">

<table>
<tr align="center" style="font-weight: bold">
<td>
Your text
</td>
<td>
Translation
</td>
</tr>
<tr>
<td>
<h:inputTextarea id="text" value="#{translator.text}" required="true" rows="5" cols="80"/>
</td>
<td>
<h:outputText value="#{translator.translatedText}"/>
</td>
</tr>
</table>
<div>
<h:commandButton id="button" value="Translate" action="#{translator.translate}"/>
</div>

</h:form>

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:

public class TextTranslator implements Serializable {

private SentenceParser sentenceParser;
@EJB private Translator translator;

@Inject public TextTranslator(SentenceParser sentenceParser) {
this.sentenceParser = sentenceParser;
}

public String translate(String text) {
StringBuilder sb = new StringBuilder();
for (String sentence: sentenceParser.parse(text)) {
sb.append(translator.translate(sentence)).append(". ");
}
return sb.toString().trim();
}
}

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!

@Stateless

public class SentenceTranslator implements Translator {
public String translate(String sentence) {
return "Lorem ipsum dolor sit amet";
}
}

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.

@Stateful

@RequestScoped
@Named("translator")
public class TranslatorControllerBean implements TranslatorController {
@Inject private TextTranslator translator;

private String inputText;

private String translatedText;

public void translate() {
translatedText = translator.translate(inputText);
}

public String getText() {
return inputText;
}

public void setText(String text) {
this.inputText = text;
}

public String getTranslatedText() {
return translatedText;
}

@Remove public void remove() {}
}

That concludes our short tour of the Weld starter examples. For more information on Weld, or to help out with development, please visit http://www.seamframework.org/Weld/Development.

Part III. Loose coupling with strong typing

Chapter 8. Producer methods

Producer methods let us overcome certain limitations that arise when a container, instead of the application, is responsible for instantiating objects. They're also the easiest way to integrate objects which are not beans into the CDI environment.

According to the spec:

A producer method acts as a source of objects to be injected, where:

• the objects to be injected are not required to be instances of beans,

• the concrete type of the objects to be injected may vary at runtime or

• the objects require some custom initialization that is not performed by the bean constructor

For example, producer methods let us:

• expose a JPA entity as a bean,

• expose any JDK class as a bean,

• define multiple beans, with different scopes or initialization, for the same implementation class, or

• vary the implementation of a bean type at runtime.

In particular, producer methods let us use runtime polymorphism with CDI. As we've seen, alternative beans are one solution to the problem of deployment-time polymorphism. But once the system is deployed, the CDI implementation is fixed. A producer method has no such limitation:

@SessionScoped

public class Preferences implements Serializable {
private PaymentStrategyType paymentStrategy;
...
@Produces @Preferred
public PaymentStrategy getPaymentStrategy() {
switch (paymentStrategy) {
case CREDIT_CARD: return new CreditCardPaymentStrategy();
case CHECK: return new CheckPaymentStrategy();
case PAYPAL: return new PayPalPaymentStrategy();
default: return null;
}
}
}

Consider an injection point:

@Inject @Preferred PaymentStrategy paymentStrategy;

This injection point has the same type and qualifier annotations as the producer method, so it resolves to the producer method using the usual CDI injection rules. The producer method will be called by the container to obtain an instance to service this injection point.

Chapter 9. Interceptors

Interceptor functionality is defined in the Java Interceptors specification. CDI enhances this functionality with a more sophisticated, semantic, annotation-based approach to binding interceptors to beans.

The Interceptors specification defines two kinds of interception points:

• lifecycle callback interception.

In addition, the EJB specification defines timeout method interception.

A business method interceptor applies to invocations of methods of the bean by clients of the bean:

public class TransactionInterceptor {

@AroundInvoke
public Object manageTransaction(InvocationContext ctx) throws Exception { ... }
}

A lifecycle callback interceptor applies to invocations of lifecycle callbacks by the container:

public class DependencyInjectionInterceptor {

@PostConstruct
public void injectDependencies(InvocationContext ctx) { ... }
}

An interceptor class may intercept both lifecycle callbacks and business methods.

A timeout method interceptor applies to invocations of EJB timeout methods by the container:

public class TimeoutInterceptor {

@AroundTimeout
public Object manageTransaction(InvocationContext ctx) throws Exception { ... }
}

Chapter 10. Decorators

Interceptors are a powerful way to capture and separate concerns which are orthogonal to the application (and type system). Any interceptor is able to intercept invocations of any Java type. This makes them perfect for solving technical concerns such as transaction management, security and call logging. However, by nature, interceptors are unaware of the actual semantics of the events they intercept. Thus, interceptors aren't an appropriate tool for separating business-related concerns.

The reverse is true of decorators. A decorator intercepts invocations only for a certain Java interface, and is therefore aware of all the semantics attached to that interface. Since decorators directly implement operations with business semantics, it makes them the perfect tool for modeling some kinds of business concerns. It also means that a decorator doesn't have the generality of an interceptor. Decorators aren't able to solve technical concerns that cut across many disparate types. Interceptors and decorators, though similar in many ways, are complementary. Let's look at some cases where decorators fit the bill.

Suppose we have an interface that represents accounts:

public interface Account {

public BigDecimal getBalance();
public User getOwner();
public void withdraw(BigDecimal amount);
public void deposit(BigDecimal amount);
}

Several different beans in our system implement the Account interface. However, we have a common legal requirement that; for any kind of account, large transactions must be recorded by the system in a special log. This is a perfect job for a decorator.

A decorator is a bean (possibly even an abstract class) that implements the type it decorates and is annotated @Decorator.

@Decorator

public abstract class LargeTransactionDecorator
implements Account {
...
}

The decorator implements the methods of the decorated type that it wants to intercept.

@Decorator

public abstract class LargeTransactionDecorator
implements Account {
@Inject @Delegate @Any Account account;
@PersistenceContext EntityManager em;

public void withdraw(BigDecimal amount) {
...
}

public void deposit(BigDecimal amount);
...
}
}

Unlike other beans, a decorator may be an abstract class. Therefore, if there's nothing special the decorator needs to do for a particular method of the decorated interface, you don't need to implement that method.

Interceptors for a method are called before decorators that apply to the method.

Chapter 12. Stereotypes

The CDI specification defines a stereotype as follows:

In many systems, use of architectural patterns produces a set of recurring bean roles. A stereotype allows a framework developer to identify such a role and declare some common metadata for beans with that role in a central place.

A stereotype encapsulates any combination of:

• a default scope, and

• a set of interceptor bindings.

A stereotype may also specify that:

• all beans with the stereotype have defaulted bean EL names, or that

• all beans with the stereotype are alternatives.

A bean may declare zero, one or multiple stereotypes. Stereotype annotations may be applied to a bean class or producer method or field.

A stereotype is an annotation, annotated @Stereotype, that packages several other annotations. For instance, the following stereotype identifies action classes in some MVC framework:

@Stereotype

@Retention(RUNTIME)
@Target(TYPE)
...
public @interface Action {}

We use the stereotype by applying the annotation to a bean.

@Action

public class LoginAction { ... }

Of course, we need to apply some other annotations to our stereotype or else it wouldn't be adding much value.

Chapter 13. Specialization, inheritance and alternatives

When you first start developing with CDI, you'll likely be dealing only with a single bean implementation for each bean type. In this case, it's easy to understand how beans get selected for injection. As the complexity of your application grows, multiple occurrences of the same bean type start appearing, either because you have multiple implementations or two beans share a common (Java) inheritance. That's when you have to begin studying the specialization, inheritance and alternative rules to work through unsatisfied or ambiguous dependencies or to avoid certain beans from being called.

The CDI specification recognizes two distinct scenarios in which one bean extends another:

• The second bean specializes the first bean in certain deployment scenarios. In these deployments, the second bean completely replaces the first, fulfilling the same role in the system.

• The second bean is simply reusing the Java implementation, and otherwise bears no relation to the first bean. The first bean may not even have been designed for use as a contextual object.

The second case is the default assumed by CDI. It's possible to have two beans in the system with the same part bean type (interface or parent class). As you've learned, you select between the two implementations using qualifiers.

The first case is the exception, and also requires more care. In any given deployment, only one bean can fulfill a given role at a time. That means one bean needs to be enabled and the other disabled. There are a two modifiers involved: @Alternative and @Specializes. We'll start by looking at alternatives and then show the guarantees that specialization adds.

Chapter 14. Java EE component environment resources

Java EE 5 already introduced some limited support for dependency injection, in the form of component environment injection. A component environment resource is a Java EE component, for example a JDBC datasource, JMS queue or topic, JPA persistence context, remote EJB or web service.

Naturally, there is now a slight mismatch with the new style of dependency injection in CDI. Most notably, component environment injection relies on string-based names to qualify ambiguous types, and there is no real consistency as to the nature of the names (sometimes a JNDI name, sometimes a persistence unit name, sometimes an EJB link, sometimes a nonportable "mapped name"). Producer fields turned out to be an elegant adaptor to reduce all this complexity to a common model and get component environment resources to participate in the CDI system just like any other kind of bean.

Fields have a duality in that they can both be the target of Java EE component environment injection and be declared as a CDI producer field. Therefore, they can define a mapping from a string-based name in the component environment, to a combination of type and qualifiers used in the world of typesafe injection. We call a producer field that represents a reference to an object in the Java EE component environment a resource.