Components and contexts
4.3 Defining components using annotations
In Seam, you can define components in one of two ways: you can use either annotations or XML. The goal of Seam is to reduce as much XML coding as possible. Therefore, annotations are the preferred mechanism for defining a Seam component. Two com-mon alternatives are the XML-based Seam component descriptor, covered in chapter 5, and Seam’s pluggable container mechanism—the integration that allows Spring beans to serve as Seam components—which is explored in chapter 15 (online). This chapter focuses on the annotation approach. The annotations that dictate how a component is defined are listed in table 4.4. As the chapter develops, I’ll introduce you to each one in detail.
This section concentrates on @Name and @Scope, which together form an integral ponent definition. The remaining annotations are auxiliary and affect how the com-ponent is processed or behaves at runtime.
Table 4.4 Seam annotations that define components and declare how they are instantiated
Annotation What it does
@Name Declares a class as a Seam component and assigns it a name. When the compo-nent name is requested, Seam instantiates a new instance of the class and binds it to the context variable with the same name.
@Scope Specifies the default scope in which the context variable is stored when an instance of the component is instantiated.
@Role (@Roles) Defines alternate name and scope pairings for the component that can be used to instantiate parallel instances of the same component for different purposes.
Multiple @Role declarations are wrapped in a @Roles annotation.
@Startup Instructs Seam to instantiate the component automatically when its assigned con-text starts (only applies to application-scoped and session-scoped components).
@Namespace Binds a URI to a Java package and used to define custom XML namespaces in the Seam component descriptor.
@Install Used to make installation of a component conditional or to provide a precedence to override another component definition. Conditions include the presence of a class on the classpath, the presence of another component, or the debug mode setting.
@AutoCreate Tells Seam to create a new instance of the component when the component name is first requested, even if the calling code doesn’t request for it to be created.
4.3.1 Giving a component a @Name
It all starts with a @Name. The most fundamental way of creating a Seam component is by adding the @Name annotation to the class declaration. This annotation is summa-rized in table 4.5. Given that every Seam component must be assigned a name, you must provide one using the value attribute of the @Name annotation.
You can place a @Name annotation on any class that you’d like to dress up as a Seam component. Keep in mind, though, that annotations are obviously only useful for classes that you can modify. See the accompanying sidebar describing the syntax of annotations if you’re unfamiliar with how to use them.
The coolest part of Seam is its ability to normalize the nonsemantic differences among components’ native types. The list of candidates for a Seam component includes
Table 4.5 The @Name annotation Name: Name
Purpose: Marks a Java class as a Seam component and assigns the component a unique name Target: TYPE (class)
Attribute Type Function
value String The name of the component. This value is used as the name of the con-text variable to which instances are bound in the component’s scope.
Default: none (required).
The syntax of annotations
Annotations are markers. They consist of a Java type—a name prefixed with an at sign (@)—and a set of attributes associated with that type. Annotations can be placed on interfaces, class definitions (types), methods, fields, parameters, and packages. The acceptable locations are defined by the annotation.
The attribute assignments for an annotation appear as a list of name-value pairs placed between a set of parentheses and separated by commas. There’s an excep-tion to this syntax rule, though. If you’re defining exactly one attribute, and the name of that attribute is value, then the attribute name and the equals sign (=) can be omitted. If the name of the attribute is not value, or you’re defining multiple attributes on a single annotation, then both the attribute name and value are required for every attribute. If you’re not declaring any attributes, the parentheses can be omitted.
Attribute values can be primitives, Java types, annotations, or arrays of the former.
When defining an array value, the items are placed between a set of curly braces and separated by commas. Again, there is an exception to this syntax rule. If the multi-valued attribute has exactly one item, the curly braces can be omitted.
■ JavaBean (POJO) – JavaBean
– Groovy class (Groovy Bean) – Spring bean3
■ EJB component
– Stateless session bean – Stateful session bean – Message-driven bean
■ JPA entity class (treated differently than JavaBean components)
Seam decorates JavaBean components with functionality equivalent to what is pro-vided by the EJB container, such as container-managed transaction management and security, shielding the rest of the application from being affected by the underlying type. What sets components in Seam apart from those in other containers is the atten-tion to the context of a component instance—the scope of its existence.
4.3.2 Putting a component in @Scope
The @Name annotation is only half of the component story in Seam. The component instance has to be put somewhere once it’s created. That’s where the @Scope annota-tion comes in. The @Scope annotaannota-tion dictates the contextual scope in which an instance of the component will be stored after it’s instantiated by the Seam container.
You can, of course, put the component instance anywhere you want using a manual assignment. The @Scope annotation just determines the default scope where Seam stores the instance. Table 4.6 lists the scope that is used for each type of component if one is not specified in the component definition.
You can override these default scope assignments by adding the @Scope annotation, summarized in table 4.7, to the class definition.
Let’s consider an example of how to put the @Name and @Scope annotations together to develop a new module for the Open 18 application.
3 Spring beans are classes that are managed by the Spring container. Seam can “borrow” a bean from the Spring container and decorate it with Seam services, just like it can with EJB components.
Component type Default scope assignment
EJB stateful session bean Conversation JPA entity class Conversation EJB stateless session bean Stateless EJB message driven bean Stateless
JavaBean (POJO) Event Table 4.6 Seam component
classifications and default scopes