JBoss Weld CDI for Java Platform

4.3 (3 reviews total)
By Ken Finnigan
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. What is a Bean?

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

Publication date:
July 2013
Publisher
Packt
Pages
122
ISBN
9781782160182

 

Chapter 1. What is a Bean?

This chapter will introduce us to beans and their history prior to Contexts and Dependency Injection (CDI) becoming a part of Java Enterprise Edition (Java EE). After a short history, we will define what a bean is and what characteristics and behavior a Java class requires to be considered a bean.

Note

JSR-299: Contexts and Dependency Injection for the Java EE platform was finalized in December 2009. CDI 1.1 is due to be released in the first half of 2013 to coincide with the release of Java EE 7.

 

The history of beans


Beans have been used to refer to many different kinds of Java classes over the years. The oldest use of a bean is from 1996, when Sun introduced JavaBeans as a term for a reusable software component for Java that defined a series of rules as to how a Java class should be developed. Those original rules have become ubiquitous to the point that the term JavaBeans is rarely, if ever, used anymore.

Since that initial use of the bean in 1996, there have been many uses of the term in third-party frameworks such as Seam and Spring. The term was also used in EE specifications for Enterprise JavaBeans (EJBs) and Java Server Faces (JSF) where they were called Managed Beans . Even though the term "bean" had been used by various specifications within the Java EE platform, there was never a consistent or clear definition of what a bean is made of and how it could be utilized.

With the release of Java EE 6 in December 2009, for the first time the Managed Bean specification brought a common standard and definition of a bean to the entire Java EE platform. This definition was expanded upon within the EJB and CDI companion specifications of Java EE 6 and will continue to be utilized as more EE specifications continue to adopt the definition of a managed bean.

 

Definition of a bean


A bean is simply a Plain Old Java Object (POJO) that is managed by a container instead of an application. With this simple definition of a bean, most of your existing Java classes can be utilized as beans with minimal to no changes, such as adding annotations.

public class MyFirstBean {
}

It may not look like much, but the preceding Java class is all that is required for the most basic of CDI beans, which use the @Dependent scope (see Chapter 4, Scopes and Contexts).

To specify a CDI scope other than @Dependent, the bean will need a means for Weld to generate a Proxy (see Chapter 2, Dependency Injection and Lookup) of the bean for injection. For a bean to be able to be proxied by the container, it needs a non-private constructor with no parameters, commonly referred to by Java developers as a default constructor. Our bean is now:

@RequestScoped
public class MyFirstBean {
  public MyFirstBean() {
  }
}

It is also possible for a bean to be proxied by the container if it does not have a constructor with any parameters, but it does require a constructor to be annotated with @Inject, such as the following:

@RequestScoped
public class MySecondBean {
  MyFirstBean firstBean;

  @Inject
  public MySecondBean(MyFirstBean firstBean) {
    this.firstBean = firstBean;
  }
}

In the preceding examples we specified @RequestScoped, but we could also have chosen @ApplicationScoped, @SessionScoped, or @ConversationScoped.

Tip

For complete details on the various scopes that are provided by CDI, see Chapter 4, Scopes and Contexts.

Any object that is bound to a lifecycle context is a bean, which enables CDI to provide support for Java EE Managed Beans and EJB Session Beans. Due to this inherent support in CDI, EJB Session Beans and Managed Beans can inject other beans into them as well as be injected into POJOs that are also beans.

When creating a CDI bean, we need to be concerned only with specifying the type and functionality of any beans that our bean will depend on to complete its work. This frees both the developer and the bean from being concerned with the following:

  • The lifecycle of the bean being injected, and how that differs from the lifecycle of the bean that requested it

  • Whether the type defined is a concrete implementation or an interface, and how the implementation for injection is to be created or retrieved

  • If other beans also inject the same bean, how it should be handled to prevent a deadlock

This loose coupling between a bean and any beans that it depends on not only simplifies the development process, but also supports different use cases through alteration of which concrete implementation is being chosen at runtime, how the bean lifecycle will operate, and which threading model a bean utilizes.

With loose coupling, we could provide an @Alternative (see Chapter 2, Dependency Injection and Lookup) implementation of a credit card provider for use in development and testing environments to prevent spurious credit card payments being triggered, with the implementation that communicates with the credit card provider used only in production.

 

Is my class a bean?


For almost every Java class that we as developers have ever written, the answer would be yes, most definitely, as long as the Java class has either a constructor with no parameters or a constructor that is annotated with @Inject.

There is only one requirement that CDI mandates for a Java class to be injected as a bean, and that's for the Java class to be packaged into an appropriate archive (such as a JAR or WAR) that contains a descriptor file called beans.xml. This descriptor file needs to be present in the META-INF folder of a JAR or the WEB-INF folder of a WAR.

It's perfectly fine for beans.xml to be completely empty or only contain the following XML content:

<beans 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/beans_1_0.xsd">
</beans>

For most applications, the sole purpose of beans.xml is to notify CDI that there are beans within the archive that need to be scanned, so that they are available to have beans injected into them as well as be injected into other beans that may not be present within this archive.

 

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.

 

Which classes are beans?


We're going to explore the different kinds of beans that Weld supports without any work on our part.

Managed Beans

As mentioned earlier, the Managed Beans specification was introduced in Java EE 6 to provide a common definition of a Managed Bean. All that's required to create a Managed Bean is to annotate it with @ManagedBean, though CDI doesn't require us to do so.

Note

JSF also has a @ManagedBean annotation to define their beans, and it's important to not confuse the two as they are separate annotations. Future releases of the JSF specification will endeavor to close this gap by utilizing the annotation from the Managed Beans specification.

Earlier in this chapter, we covered the requirements for constructors of a Java class to be a Managed Bean, but the CDI specification states that it must also meet the following conditions:

  • It is not a non-static inner class

  • It is a concrete class or is annotated @Decorator

  • It is not annotated with an EJB component-defining annotation or declared as an EJB bean class in ejb-jar.xml

  • It does not implement javax.enterprise.inject.spi.Extension

According to the preceding conditions, Java Persistence API (JPA) entities are also Managed Beans! Trying to use entities as Managed Beans will cause runtime issues when attempting to persist Managed Beans that have been proxied by CDI.

Tip

We recommend to not directly inject an entity class into your beans, and they should not be assigned a scope other than @Dependent.

Session Beans

Session Beans can take advantage of CDI just like any other bean, though there are a few restrictions due to Session Beans having their lifecycle managed separate to CDI.

Message-driven and entity beans are not contextual objects in the CDI sense, so they are not able to be injected into other beans. It is possible to inject beans into a message-driven bean, and use interceptors and decorators to utilize some of the CDI functionalities that are available.

As the EJB container controls the lifecycle of a stateless Session Bean and a singleton Session Bean, there is no need to specify any CDI scope for these, but a stateful Session Bean may use any scope it requires.

Producers

In these final two sections, we will introduce producers, both method and field, which can be used to provide a CDI bean that isn't a Java class, per se. Producers are often useful in a situation where it is not known during development which particular qualified bean instance needs to be used, and producers allow us to create a bean that depends on runtime information for its creation.

Producers provide a source for new bean instances. A producer will be invoked by Weld when there is no instance of that bean in the required context.

We will cover producers in detail in Chapter 5, Producers.

Producer methods

To create a producer on a method, all that's required is to annotate the method with @Produces, along with any other qualifiers that we want the bean being produced to fulfill.

Note

Though producer methods can be called by our application, just as any other method, the returned bean will be completely outside the control of CDI. If the method has parameters, they will not be injected with beans at all; they would need to be passed just like any method call.

We'll define a producer method for UserAccount from an earlier example:

public class AccountManager {
  @Produces
  @User
  Account getUserAccount() {
    ...
  }
}

The bean created from this producer can then be injected by using:

@Inject
@User
Account userAccount;

We can also add @Named to allow the bean to be accessed via EL, which for this example would be userAccount.

Producer methods can also declare parameters, and the container will retrieve a bean that matches the bean type and qualifiers that can be passed into the method.

Producer fields

Producer fields are a simpler alternative to producer methods, as they remove the need to create a method and thus reduce boilerplate code. If we converted the producer method from the previous example, it would be as follows:

public class AccountManager {
  @Produces
  @User
  Account userAccount = ...;
}

In situations where you have a bean with a field that you want to make available to other beans, using a producer field is often the best way to achieve this as it only involves one or more annotations being added to the existing field definition.

We can also add @Named to the producer field and access the bean with the same EL name from the previous example.

 

Summary


We covered a lot of information in this chapter about CDI concepts around what a bean is, such as qualifiers, scopes, alternatives, and producers. It's a lot to comprehend in one go, particularly if dependency injection is not a concept that is familiar.

As we progress through the following chapters, each concept that we've discussed here will become clearer as we delve into further details and provide more examples.

About the Author

  • Ken Finnigan

    Ken Finnigan is a Senior Software Engineer at Red Hat, technical lead of the JBoss Portlet Bridge project, a member of the GateIn development team, and the founder of the Arquillian Portal Extension. As a consultant and engineer he has over 15 years development experience with enterprises throughout the world using technologies that include Java EE frameworks (JSF, CDI, EJB3, Hibernate, and Seam), Java testing frameworks (Arquillian, JUnit, and TestNG), Maven, Ant, and a variety of others. In his spare time, he is a committer for Apache DeltaSpike, ShrinkWrap, and Arquillian. He is also the author of GateIn Cookbook, Packt Publishing.

    Browse publications by this author

Latest Reviews

(3 reviews total)
Good
Good
Excellent
Book Title
Access this book, plus 7,500 other titles for FREE
Access now