Book Image

JBoss Weld CDI for Java Platform

By : Kenneth Finnigan
Book Image

JBoss Weld CDI for Java Platform

By: Kenneth Finnigan

Overview of this book

CDI simplifies dependency injection for modern application developers by taking advantage of Java annotations and moving away from complex XML, while at the same time providing an extensible and powerful programming model. "JBoss Weld CDI for Java Platform" is a practical guide to CDI's dependency injection concepts using clear and easy-to-follow examples. This will help you take advantage of the power behind CDI, as well as providing a firm understanding of how to use it within your applications. "JBoss Weld CDI for Java Platform" covers all the major aspects of CDI, breaking it down into understandable pieces. This book will take you through many examples of how these concepts can be utilized, helping you get up and running quickly and painlessly. "JBoss Weld CDI for Java Platform" gives you an insight into the different scopes provided by CDI and the use cases for which each has been designed. You will learn everything about dependency injection, scopes, events, producers, and more from JBoss Weld CDI, as well as how producers can create new beans for consumption within your application. You will also learn how to build a real world application with CDI using JSF and AngularJS for different web interfaces.
Table of Contents (17 chapters)
JBoss Weld CDI for Java Platform
Credits
About the Author
About the Reviewer
www.PacktPub.com
Preface
Index

What does it mean to be a bean?


According to the CDI specification:

A bean comprises the following attributes:

  • A (non-empty) set of bean types

  • A (non-empty) set of qualifiers

  • A scope

  • Optionally, a bean EL name

  • A set of interceptor bindings

  • A bean implementation

Furthermore, a bean may or may not be an alternative.

Bean types

In most cases, beans acquire references to other beans through dependency injection. The point at which a bean is injected will specify the type of that bean and a set of qualifiers. With the help of the bean type and qualifiers, Weld determines the implementation of a bean to provide for injection.

A bean type can be a class or interface that is visible to clients that wish to inject it. For instance, an EJB Session Bean implementation is not visible to clients, but its @Local interface is visible.

Note

EJB remote interfaces are not bean types of a Session Bean, and therefore they cannot be injected directly. They must be injected by defining a resource.

public class CandyStore extends CommonStore
implements Store<Candy> {
  ...
}

In this Java class, there are four bean types defined: CandyStore, CommonStore, Store<Candy>, and the implicit type java.lang.Object. An interesting point to note is that a parameterized type is considered a bean type by CDI, but only if it contains an actual type parameter and not a wildcard.

We are able to restrict which bean types are valid for any given Java class with the @Typed annotation by providing a defined set of bean types that can be accepted. We can restrict the types from the previous example to only Store<Candy> and the implicit java.lang.Object type, with the following:

@Typed(Store.class)
public class CandyStore extends CommonStore
implements Store<Candy> {
  ...
}

Qualifiers

A qualifier allows us to disambiguate a type without the need to leave type-safety and revert to string-based names, which we all know are fodder for runtime errors. All we need for defining a qualifier is to create an annotation that is annotated with @Qualifier.

@Qualifier
@Target( { TYPE, METHOD, PARAMETER, FIELD } )
@Retention( RUNTIME )
public @interface User {}

Here, we've defined a qualifier called User. Specifying RUNTIME retention informs the Java VM that we want the annotation information recorded in the class file of any bean that specifies this qualifier, so that it may be read at runtime. The values of TYPE, METHOD, PARAMETER, and FIELD specify valid locations within a bean where the qualifier may be placed.

Note

The @Retention values are found in java.lang.annotation.RetentionPolicy and the @Target values are found in java.lang.annotation.ElementType.

With our qualifier annotation, we are now able to disambiguate an injection point. The following injection point has a bean type of Account and a qualifier of @User:

@Inject
@User
Account userAccount;

The Weld container searches for a bean that matches the same bean type and all the qualifiers and each injection point that has been defined. If Weld doesn't find exactly one match, an error is reported during startup that there is an ambiguous injection point, which is Weld's way of telling you that there are too many beans that match the bean type and qualifiers.

To inform Weld that a bean has a specific qualifier, we annotate the bean class with it. The following bean would match the injection point from the previous code snippet:

@User
public class UserAccount implements Account {
  ...
}

Note

Any bean or injection point that does not explicitly specify a qualifier will have the default qualifier @Default assigned to it.

Scope

In the previous examples, we've utilized the CDI scopes that are provided for us, but what is a scope? A scope is the means by which a bean specifies its lifecycle and the visibility of its instances.

For instance, @SessionScoped binds a bean to a user session and is shared across all requests that execute in the context of that session.

Note

Once a bean is bound to its context, it cannot be removed from that context. The bean will remain in that context until the time the context is destroyed by the container. It's especially important to keep this in mind when developing beans that will hold large amounts of data and for how long that data needs to be retained.

Expression Language (EL)

A bean can be referenced from non-Java code if it supports Unified EL expressions, such as with JSF and JSP pages, but it requires an EL name to be defined.

The @Named annotation specifies the EL name for a bean, as follows:

@Named("book")
public class HistoryBook implements Serializable {
  ...
}

We can now access the bean in a JSF page:

<h:outputText value="#{book.isbn}" />

If we aren't particular about what EL name a bean is given, we can specify @Named without any value and it will default to the unqualified class name, with the first character converted to lower case. In the previous example, this would give us an EL name of historyBook.

Alternatives

If we need to vary which implementation is chosen depending on the deployment environment or some other factor, we can create an alternative bean that can be activated when needed.

For instance, if we want to create a mock or dummy implementation that is only used in testing environments, we can write the following:

@Alternative
public class DummyLogger extends LoggerImpl {
  ...
}

It's general practice to only annotate a bean with @Alternative when there is at least one other implementation of an interface it implements or any of its bean types, otherwise there wouldn't be anything for it to be an alternative of.

Alternatives are chosen by selecting an alternative in the CDI descriptor file, beans.xml, of the JAR or WAR that uses it.

This topic will be covered in greater detail in Chapter 2, Dependency Injection and Lookup.