CHAPTER 3

image

Enterprise Applications

No technology exists in a vacuum, and JPA is no different in this regard. Although the fat-client style of application demonstrated in the previous chapter is a viable use of JPA, the majority of enterprise Java applications are deployed to an application server, typically using Java EE web technologies, and possibly other technologies as well. Therefore it is essential to understand the components that make up a deployed application and the role of JPA in this environment.

We will begin with an overview of the major Java EE technologies relevant to persistence. As part of this overview, we will describe the EJB component model, demonstrating the basic syntax for some of the different types of EJB's.

We will then go on to briefly cover the standard dependency injection (DI) mechanism, mostly using the Java EE Contexts and Dependency Injection (CDI) approach. This chapter is not intended to be a complete or detailed exploration of Java EE or component frameworks, and we can't possibly go into all of the DI frameworks in the DI-sphere, or even the facilities offered by CDI. However, the CDI and EJB examples are fairly typical of DI in general and should give a general idea of how JPA can be used with DI-enabled components, be they of the Java EE variety or some other DI container component, such as Spring or Guice.

We will then look at transactions, another application server technology that has had a major impact on applications using JPA. Transactions are a fundamental element of any enterprise application that needs to ensure data integrity.

Finally, we will demonstrate how to use the technologies described in this chapter within the context of how persistence integrates into each component technology. We will also revisit the Java SE application from the previous chapter and retarget it to the enterprise platform.

Application Component Models

The word "component" has taken on many meanings in software development, so let’s begin with a definition. A component is a self-contained, reusable software unit that can be integrated into an application. Clients interact with components via a well-defined contract. In Java, the simplest form of software component is the JavaBean, commonly referred to as just a bean. Beans are components implemented in terms of a single class whose contract is defined by the naming patterns of the methods on the bean. The JavaBean naming patterns are so common now that it is easy to forget that they were originally intended to give user-interface builders a standard way of dealing with third-party components.

In the enterprise space, components focus more on implementing business services, with the contract of the component defined in terms of the business operations that can be carried out by that component. The traditional component model for Java EE has always been the EJB model, which defines ways to package, deploy, and interact with self-contained business services. Then CDI came along and brought a more powerful and flexible model of managed bean component, with CDI beans being either EJB's or non-EJB Java classes.

Choosing whether or not to use a component model in your application is largely a personal preference, but is generally a good design choice. Using components requires organizing the application into layers, with business services living in the component model and presentation services layered on top of it.

Historically, one of the challenges in adopting components in Java EE was the complexity of implementing them. With that problem largely solved, we are left with the following benefits that a well-defined set of business services brings to an application:

  • Loose coupling: Using components to implement services encourages loose coupling between layers of an application. The implementation of a component can change without any impact to the clients or other components that depend on it.
  • Dependency management: Dependencies for a component can be declared in metadata and automatically resolved by the container.
  • Lifecycle management: The lifecycle of components is well defined and managed by the application server. Component implementations can participate in lifecycle operations to acquire and release resources, or perform other initialization and shutdown behavior.
  • Declarative container services: Business methods for components are intercepted by the application server in order to apply services such as concurrency, transaction management, security, and remoting.
  • Portability: Components that comply to Java EE standards and that are deployed to standards-based servers can be more easily ported from one compliant server to another.
  • Scalability and reliability: Application servers are designed to ensure that components are managed efficiently with an eye to scalability. Depending on the component type and server configuration, business operations implemented using components can retry failed method calls or even fail over to another server in a cluster.

As you read this book, you will notice that in some cases an example will make use of a component to house the business logic and invoke the Java Persistence API. In many cases it will be a session bean, in other cases it will be a non-EJB CDI bean, and in still others it will be a CDI managed session bean (session bean with a scope). Session beans will be the preferred component because they are the simplest to write and configure and a natural fit for interacting with JPA. The actual component type we use is less important (the type of component is largely substitutable as long as it is managed by a container that supports JPA and transactions) than illustrating how components fit in with JPA and can invoke JPA.

Session Beans

Session beans are a component technology designed to encapsulate business services. The client accessible operations supported by the service may be defined using a Java interface, or in the absence of an interface, just the set of public methods on the bean implementation class. The bean class is little more than a regular Java class, and yet, by virtue of being part of the EJB component model, the bean has access to a wide array of container services. The significance of the name session bean has to do with the way in which clients access and interact with them. Once a client acquires a reference to a session bean from the server, it starts a session with that bean and can invoke business operations on it.

There are three types of session bean: stateless, stateful, and singleton. Interaction with a stateless session bean begins at the start of a business method call and ends when the method call completes. There is no state that carries over from one business operation to the other. An interaction with stateful session beans becomes more of a conversation that begins from the moment the client acquires a reference to the session bean and ends when the client explicitly releases it back to the server. Business operations on a stateful session bean can maintain state on the bean instance across calls. We will provide more detail on the implementation considerations of this difference in interaction style as we describe each type of session bean.

Singleton session beans can be considered a hybrid of stateless and stateful session beans. All clients share the same singleton bean instance, so it becomes possible to share state across method invocations, but singleton session beans lack the conversational contract and mobility of stateful session beans. State on a singleton session bean also raises issues of concurrency that need to be taken into consideration when deciding whether or not to use this style of session bean.

As with most component containers, clients in an EJB container do not interact directly with a session bean instance. The client references and invokes an implementation of the business interface or bean class provided by the server. This implementation class acts as a proxy to the underlying bean implementation. This decoupling of client from bean allows the server to intercept method calls in order to provide the services required by the bean, such as transaction management. It also allows the server to optimize and reuse instances of the session bean class as necessary.

In the following sections we will discuss session beans using synchronous business method invocations. Asynchronous business methods offer an alternative invocation pattern involving futures, but are beyond the scope of this book.

Stateless Session Beans

As we mentioned, a stateless session bean sets out to complete an operation within the lifetime of a single method. Stateless beans can implement many business operations, but each method cannot assume that any other was invoked before it.

This might sound like a limitation of the stateless bean, but it is by far the most common form of business service implementation. Unlike stateful session beans, which are good for accumulating state during a conversation (such as the shopping cart of a retail application), stateless session beans are designed to carry out independent operations very efficiently. Stateless session beans can scale to large numbers of clients with minimal impact to overall server resources.

Defining a Stateless Session Bean

A session bean is defined in two parts:

  • Zero or more business interfaces that define what methods a client can invoke on the bean. When no interface is defined, the set of public methods on the bean implementation class forms a logical client interface.
  • A class that implements these interfaces, called the bean class, which is marked with the @Stateless annotation.

Whether you want to front your session bean with an actual interface or not is a matter of preference. We will show examples of both, but will generally not use the interface in subsequent examples.

Let’s first look at an interfaced version of a stateless session bean. Listing 3-1 shows the business interface that will be supported by this session bean. In this example, the service consists of a single method, sayHello(), which accepts a String argument corresponding to a person’s name and returns a String response. There is no annotation or parent interface to indicate that this is a business interface. When implemented by the session bean, it will be automatically treated as a local business interface, meaning that it is accessible only to clients within the same application server. A second type of business interface for remote clients is also possible but not often used.

Listing 3-1.  The Business Interface for a Session Bean

public interface HelloService {
    public String sayHello(String name);
}

Now let’s consider the implementation, which is shown in Listing 3-2. This is a regular Java class that implements the HelloService business interface. The only thing unique about this class is the @Stateless annotation1 that marks it as a stateless session bean. The business method is implemented without any special constraints or requirements. This is a regular class that just happens to be an EJB.

Listing 3-2.  The Bean Class Implementing the HelloService Interface

@Stateless
public class HelloServiceBean implements HelloService {
    public String sayHello(String name) {
        return "Hello, "  + name;
    }
}

In terms of API design, using an interface is probably the best way to expose a session bean's operations, since it separates the interface from the implementation. However, the current norm is to implement components as simple classes containing the business logic without an interface. Using this approach, the session bean would simply be as shown in Listing 3-3.

Listing 3-3.  A Session Bean with No Interface

@Stateless
public class HelloService {
    public String sayHello(String name) {
        return “Hello, “ + name;
    }
}

The logical interface of the session bean consists of its public methods; in this case, the sayHello() method. Clients use the HelloServiceBean class as if it were an interface, and must disregard any nonpublic methods or details of the implementation. Under the covers, the client will be interacting with a proxy that extends the bean class and overrides the business methods to provide the standard container services.

Lifecycle Callbacks

Unlike a regular Java class used in application code, the server manages the lifecycle of a stateless session bean. The server decides when to create and remove bean instances and has to initialize the services for a bean instance after it is constructed, but before the business logic of the bean is invoked. Likewise, the bean might have to acquire a resource, such as a JDBC data source, before business methods can be used. However, in order for the bean to acquire a resource, the server must first have completed initializing its services for the bean. This limits the usefulness of the constructor for the class because the bean won’t have access to any resources until server initialization has completed.

To allow both the server and the bean to achieve their initialization requirements, EJBs support lifecycle callback methods that are invoked by the server at various points in the bean’s lifecycle. For stateless session beans, there are two lifecycle callbacks: PostConstruct and PreDestroy. The server will invoke the PostConstruct callback as soon as it has completed initializing all the container services for the bean. In effect, this replaces the constructor as the location for initialization logic because it is only here that container services are guaranteed to be available. The server invokes the PreDestroy callback immediately before the server releases the bean instance to be garbage-collected. Any resources acquired during PostConstruct that require explicit shutdown should be released during PreDestroy.

Listing 3-4 shows a stateless session bean that acquires a reference to a java.util.logging.Logger instance during the PostConstruct callback, identified by the @PostConstruct marker annotation. Likewise, a PreDestroy callback is identified by the @PreDestroy annotation.

Listing 3-4.  Using the PostConstruct Callback to Acquire a Logger

@Stateless
public class LoggerBean {
    private Logger logger;

    @PostConstruct
    void init() {
        logger = Logger.getLogger("notification");
    }

    public void logMessage(String message) {
        logger .info(message);
    }
}

Stateful Session Beans

In our introduction to session beans, we described the difference between stateless and stateful beans as being based on the interaction style between client and server. In the case of stateless session beans, that interaction started and ended with a single method call. Sometimes clients need to issue multiple requests and have each request be able to access or consider the results of previous requests. Stateful session beans are designed to handle this scenario by providing a dedicated service to a client that starts when the client obtains a reference to the bean and ends only when the client chooses to end the conversation.

The quintessential example of the stateful session bean is the shopping cart of an e-commerce application. The client obtains a reference to the shopping cart, starting the conversation. Over the span of the user session, the client adds or removes items from the shopping cart, which maintains state specific to the client. Then, when the session is complete, the client completes the purchase, causing the shopping cart to be removed.

This is not unlike using a nonmanaged Java object in application code. You create an instance, invoke operations on the object that accumulate state, and then dispose of the object when you no longer need it. The only difference with the stateful session bean is that the server manages the actual object instance and the client interacts with that instance indirectly through a proxy object.

Stateful session beans offer a superset of the functionality available in stateless session beans. The features that we covered for stateless session beans apply equally to stateful session beans.

Defining a Stateful Session Bean

Now that we have established the use case for a stateful session bean, let’s look at how to define one. Similar to the stateless session bean, a stateful session bean may or may not have an interface implemented by a single bean class. Listing 3-5 shows the bean class for the ShoppingCart stateful session bean. The bean class has been marked with the @Stateful annotation to indicate to the server that the class is a stateful session bean.

Listing 3-5.  Implementing a Shopping Cart Using a Stateful Session Bean

@Stateful
public class ShoppingCart {
    private HashMap<String,Integer> items = new HashMap<String,Integer>();

    public void addItem(String item, int quantity) {
        Integer orderQuantity = items.get(item);
        if (orderQuantity == null) {
            orderQuantity = 0;
        }
        orderQuantity += quantity;
        items.put(item, orderQuantity);
    }

    public void removeItem(String item, int quantity) {
        // ...
    }

    public Map<String,Integer> getItems() {
        // ...
    }

    // ...

    @Remove
    public void checkout(int paymentId) {
        // store items to database
        // ...
    }

    @Remove
    public void cancel() {
    }
}

There are two things different in this bean compared with the stateless session beans we have been dealing with so far.

The first difference is that the bean class has state fields that are modified by the business methods of the bean. This is allowed because the client that uses the bean effectively has access to a private instance of the session bean on which to make changes.

The second difference is that there are methods marked with the @Remove annotation. These are the methods that the client will use to end the conversation with the bean. After one of these methods has been called, the server will destroy the bean instance, and the client reference will throw an exception if any further attempt is made to invoke business methods. Every stateful session bean must define at least one method marked with the @Remove annotation, even if the method doesn’t do anything other than serve as an end to the conversation. In Listing 3-5, the checkout() method is called if the user completes the shopping transaction, although cancel() is called if the user decides not to proceed. The session bean is removed in either case.

Lifecycle Callbacks

Like the stateless session bean, the stateful session bean also supports lifecycle callbacks in order to facilitate bean initialization and cleanup. It also supports two additional callbacks to allow the bean to gracefully handle passivation and activation of the bean instance. Passivation is the process by which the server serializes the bean instance so that it can either be stored offline to free up resources or replicated to another server in a cluster. Activation is the process of deserializing a passivated session bean instance and making it active in the server once again. Because stateful session beans hold state on behalf of a client and are not removed until the client invokes one of the remove methods on the bean, the server cannot destroy a bean instance to free up resources. Passivation allows the server to temporarily reclaim resources while preserving session state.

Before a bean is passivated, the server will invoke the PrePassivate callback. The bean uses this callback to prepare the bean for serialization, usually by closing any live connections to other server resources. The PrePassivate method is identified by the @PrePassivate marker annotation. After a bean has been activated, the server will invoke the PostActivate callback. With the serialized instance restored, the bean must then reacquire any connections to other resources that the business methods of the bean might be depending on. The PostActivate method is identified by the @PostActivate marker annotation. Listing 3-6 shows a session bean that makes full use of the lifecycle callbacks to maintain a JDBC connection. Note that only the JDBC Connection is explicitly managed. As a resource connection factory, the server automatically saves and restores the data source during passivation and activation.

Listing 3-6.  Using Lifecycle Callbacks on a Stateful Session Bean

@Stateful
public class OrderBrowser {
    DataSource ds;
    Connection conn;

    @PostConstruct
    void init() {
        // acquire the data source
        // ...

        acquireConnection();
    }
    
    @PrePassivate
    void passivate() { releaseConnection(); }

    @PostActivate
    void activate() { acquireConnection(); }

    @PreDestroy
    void shutdown() { releaseConnection(); }
    
    private void acquireConnection() {
        try {
            conn = ds.getConnection();
        } catch (SQLException e) {
            throw new EJBException(e);
        }
    }

    private void releaseConnection() {
        try {
            conn.close();
        } catch (SQLException e) {
        } finally {
            conn = null;
        }
    }

    public Collection<Order> listOrders() {
        // ...
    }

    @Remove
    public void remove() {}
}

Singleton Session Beans

Two of the most common criticisms of the stateless session bean have been the perceived overhead of bean pooling and the inability to share state via static fields. The singleton session bean attempts to provide a solution to both concerns by providing a single shared bean instance that can both be accessed concurrently and used as a mechanism for shared state. Singleton session beans share the same lifecycle callbacks as a stateless session bean, and server-managed resources such as persistence contexts behave the same as if they were part of a stateless session bean. But the similarities end there because singleton session beans have a different overall lifecycle than stateless session beans and have the added complexity of developer-controlled locking for synchronization.

Unlike other session beans, the singleton can be declared to be created eagerly during application initialization and exist until the application shuts down. Once created, it will continue to exist until the container removes it, regardless of any exceptions that occur during business method execution. This is a key difference from other session bean types because the bean instance will never be re-created in the event of a system exception.

The long life and shared instance of the singleton session bean make it the ideal place to store common application state, whether read-only or read-write. To safeguard access to this state, the singleton session bean provides a number of concurrency options depending on the needs of the application developer. Methods can be completely unsynchronized for performance, or automatically locked and managed by the container.

Defining a Singleton Session Bean

Following the pattern of stateless and stateful session beans, singleton session beans are defined using the @Singleton annotation. Singleton session beans can include an interface or use a no-interface view. Listing 3-7 shows a simple singleton session bean with a no-interface view to track the number of visits to a web site.

Listing 3-7.  Implementing a Singleton Session Bean

@Singleton
public class HitCounter {
    int count;

    public void increment() { ++count; }

    public void getCount() { return count; }

    public void reset() { count = 0; }
}

If you compare the HitCounter bean in Listing 3-7 with the stateless and stateful session beans defined earlier, you can see two immediate differences. Unlike the stateless session bean, there is state in the form of a count field used to capture the visit count. But unlike the stateful session bean, there is no @Remove annotation to identify the business method that will complete the session.

By default, the container will manage the synchronization of the business methods to ensure that data corruption does not occur. In this example, that means all access to the bean is serialized so that only one client is invoking a business method on the instance at any time.

The lifecycle of the singleton session bean is tied to the lifecycle of the overall application. The container determines the point when the singleton instance gets created unless the bean class is annotated with the @Startup annotation to force eager initialization when the application starts. The container can create singletons that do not specify eager initialization lazily, but this is vendor-specific and cannot be assumed.

Lifecycle Callbacks

The lifecycle callbacks for singleton session beans are the same as for stateless session beans: PostConstruct and PreDestroy. The container will invoke the PostConstruct callback after server initialization of the bean instance and likewise invoke the PreDestroy callback prior to disposing of the bean instance. The key difference is that for singleton session beans PreDestroy is invoked only when the application shuts down as a whole. It will therefore be called only once, whereas the lifecycle callbacks of stateless session beans are called frequently as bean instances are created and destroyed.

Servlets

Servlets are a component technology designed to serve the needs of web developers who need to respond to HTTP requests and generate dynamic content in return. Servlets are the oldest and most popular technology introduced as part of the Java EE platform. They are the foundation for technologies such as JavaServer Pages (JSP) and the backbone of web frameworks such as JavaServer Faces (JSF).

Although you might have some experience with servlets, it is worth describing the impact that web application models have had on enterprise application development. Because of its reliance on the HTTP protocol, the Web is inherently a stateless medium. Much like the stateless session beans described earlier, a client makes a request, the server triggers the appropriate service method in the servlet, and content is generated and returned to the client. Each request is entirely independent from the last.

This presents a challenge because many web applications involve some kind of conversation between the client and the server in which the previous actions of the user influence the results returned on subsequent pages. To maintain that conversational state, many early applications attempted to dynamically embed context information into URLs. Unfortunately, not only does this technique not scale very well but it also requires a dynamic element to all content generation that makes it difficult for nondevelopers to write content for a web application.

Servlets solve the problem of conversational state with the session. Not to be confused with the session bean, the HTTP session is a map of data associated with a session id. When the application requests that a session be created, the server generates a new id and returns an HTTPSession object that the application can use to store key/value pairs of data. It then uses techniques such as browser cookies to link the session id with the client, tying the two together into a conversation. For web applications, the client is largely ignorant of the conversational state that is tracked by the server.

Using the HTTP session effectively is an important element of servlet development. Listing 3-8 demonstrates the steps required to request a session and store conversational data in it. In this example, assuming that the user has logged in, the servlet stores the user id in the session, making it available for use in all subsequent requests by the same client. The getSession() call on the HttpServletRequest object will either return the active session or create a new one if one does not exist. Once obtained, the session acts like a map, with key/value pairs set and retrieved with the setAttribute() and getAttribute() methods, respectively. As you'll see later in this chapter, the servlet session, which stores unstructured data, is sometimes paired with a stateful session bean to manage session information with the benefit of a well-defined business interface.

Listing 3-8.  Maintaining Conversational State with a Servlet

public class LoginServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String userId = request.getParameter("user");
        HttpSession session = request.getSession();
        session.setAttribute("user", userId);
        // ...
    }
}

The rise of application frameworks targeted to the Web has also changed the way in which we develop web applications. Application code written in servlets is rapidly being replaced with application code further abstracted from the base model using frameworks such as JSF. When working in an environment such as this, basic application persistence issues, such as where to acquire and store the entity manager and how to effectively use transactions quickly, become relevant.

Although we will explore some of these issues, persistence in the context of a framework such as JSF is beyond the scope of this book. As a general solution, we recommend adopting a component model in which to focus persistence operations. Session beans, for example, are easily accessible from anywhere within a Java EE application, making them perfect neutral ground for business services. The ability to exchange entities inside and outside of the session bean model means that the results of persistence operations will be directly usable in web frameworks without having to tightly couple your presentation code to the persistence API.

Dependency Management and CDI

The business logic of a Java EE component is typically not completely self-contained. More often than not, the implementation has dependencies on other resources. This might include server resources, such as a JDBC data source, or application-defined resources, such as another component or entity manager for a specific persistence unit. The core Java EE platform contains some fairly limited support for injecting dependencies into a limited number of predefined server resources, such as data sources, managed transactions, and others. However, the CDI standard goes well beyond simple dependency injection (DI) and provides an extensive framework to support a full range of requirements, from the trivial to the exotic. We will begin by describing the basic concepts and support contained within the platform from before CDI and then move on to CDI and its contextual DI model.

Java EE components support the notion of references to resources. A reference is a named link to a resource that can be resolved dynamically at runtime from within application code or resolved automatically by the container when the component instance is created. We’ll cover each of these scenarios shortly.

A reference consists of two parts: a name and a target. The name is used by application code to resolve the reference dynamically, whereas the server uses target information to find the resource the application is looking for. The type of resource to be located determines the type of information required to match the target. Each resource reference requires a different set of information specific to the resource type to which it refers.

A reference is declared using one of the resource reference annotations: @Resource, @EJB, @PersistenceContext, or @PersistenceUnit. These annotations can be placed on a class, field, or setter method. The choice of location determines the default name of the reference, and whether or not the server resolves the reference automatically.

Dependency Lookup

The first strategy for resolving dependencies in application code that we will discuss is called dependency lookup. This is the traditional form of dependency management in Java EE, in which the application code is responsible for looking up a named reference using the Java Naming and Directory Interface (JNDI).

All the resource annotations support an attribute called name that defines the JNDI name of the reference. When the resource annotation is placed on the class definition, this attribute is mandatory. If the resource annotation is placed on a field or a setter method, the server will generate a default name. When using dependency lookup, annotations are typically placed at the class level, and the name is explicitly specified. Placing a resource reference on a field or setter method has other effects besides generating a default name that we will discuss in the next section.

The role of the name is to provide a way for the client to resolve the reference dynamically. Every Java EE application server supports JNDI, even though it is less frequently used by applications since the advent of dependency injection, and each Java EE component has its own locally scoped JNDI naming context called the environment naming context. The name of the reference is bound into the environment naming context, and when it is looked up using the JNDI API, the server resolves the reference and returns the target of the reference.

Consider the DeptService session bean shown in Listing 3-9. It has declared a dependency on a session bean using the @EJB annotation and given it the name “deptAudit.” The beanInterface element of the @EJB annotation references the session bean class. In the PostConstruct callback, the audit bean is looked up and stored in the audit field. The Context and InitialContext interfaces are both defined by the JNDI API. The lookup() method of the Context interface is the traditional way to retrieve objects from a JNDI context. To find the reference named deptAudit, the application looks up the name “java:comp/env/deptAudit” and casts the result to AuditService. The prefix “java:comp/env/” that was added to the reference name indicates to the server that the environment naming context should be searched to find the reference. If the name is incorrectly specified, the lookup will fail.

Listing 3-9.  Looking Up an EJB Dependency

@Stateless
@EJB(name="deptAudit", beanInterface=AuditService.class)
public class DeptService {
    private AuditService audit;

    @PostConstruct
    void init() {
        try {
            Context ctx = new InitialContext();
            audit = (AuditService) ctx.lookup("java:comp/env/deptAudit");
        } catch (NamingException e) {
            throw new EJBException(e);
        }
    }

    // ...
}

Using the JNDI API to look up resource references from the environment naming context is supported by all Java EE components. It is, however, a somewhat cumbersome method of finding a resource because of the exception-handling requirements of JNDI. EJBs also support an alternative syntax using the lookup() method of the EJBContext interface. The EJBContext interface (and subinterfaces such as SessionContext) is available to any EJB and provides the bean with access to runtime services such as the timer service. Listing 3-10 shows the same example as Listing 3-9 using the lookup() method. The SessionContext instance in this example is provided via a setter method that is called by the container. We will revisit this example later in the section called “Referencing Server Resources” to see how it is invoked.

Listing 3-10.  Using the EJBContext lookup() Method

@Stateless
@EJB(name="deptAudit", beanInterface=AuditService.class)
public class DeptService  {
    SessionContext context;
    AuditService audit;

    public void setSessionContext(SessionContext context) {
        this.context = context;
    }

    @PostConstruct
    public void init() {
        audit = (AuditService) context.lookup("deptAudit");
    }

    // ...
}

The EJBContext lookup() method has two advantages over the JNDI API. The first is that the argument to the method is the name exactly as it was specified in the resource reference. The second is that only runtime exceptions are thrown from the lookup() method so the checked exception handling of the JNDI API can be avoided. Behind the scenes, the exact same sequence of JNDI API calls from Listing 3-9 is being made, but the JNDI exceptions are handled automatically.

Dependency Injection

When a resource annotation is placed on a field or setter method, two things occur. First, a resource reference is declared just as if it had been placed on the bean class (similar to the way the @EJB annotation worked in the example in Listing 3-9), and the name for that resource will be bound into the environment naming context when the component is created. Second, the server does the lookup automatically on your behalf and sets the result into the instantiated class.

The process of automatically looking up a resource and setting it into the class is called dependency injection because the server is said to inject the resolved dependency into the class. This technique, one of several commonly referred to as inversion of control, removes the burden of manually looking up resources from the JNDI environment context.

Dependency injection is considered a best practice for application development, not only because it reduces the need for JNDI lookups but also because it simplifies testing. Without any JNDI API code in the class that has dependencies on the application server runtime environment, the bean class can be instantiated directly in a unit test. The developer can then manually supply the required dependencies and test the functionality of the class in question instead of worrying about how to work around the JNDI lookup.

Field Injection

The first form of dependency injection is called field injection. Injecting a dependency into a field means that after the server looks up the dependency in the environment naming context, it assigns the result directly into the annotated field of the class. Listing 3-11 revisits the example from Listing 3-9 and demonstrates a simpler use of the @EJB annotation, this time by injecting the result into the audit field. The directory interface code used before is gone, and the business methods of the bean can assume that the audit field holds a reference to the AuditService bean.

Listing 3-11.  Using Field Injection

@Stateless
public class DeptService {
    @EJB AuditService audit;

    // ...
}

Field injection is certainly the easiest to implement, and the examples in this book will always opt to use this form rather than the dynamic lookup form. The only thing to consider with field injection is that if you are planning on unit testing, you need either to add a setter method or make the field accessible to your unit tests to manually satisfy the dependency. Private fields, although legal, require unpleasant hacks if there is no accessible way to set their value. Consider package scope for field injection if you want to unit test without having to add a setter.

We mentioned in the previous section that a name is automatically generated for the reference when a resource annotation is placed on a field or setter method. For completeness, we will describe the format of this name, but it is unlikely that you will find many opportunities to use it. The generated name is the fully qualified class name, followed by a forward slash and then the name of the field or property. This means that if the DeptService bean is located in the persistence.session package, the injected EJB referenced in Listing 3-9 would be accessible in the environment naming context under the name “persistence.session.DeptService/audit”. Specifying the name element for the resource annotation will override this default value.

Setter Injection

The second form of dependency injection is called setter injection and involves annotating a setter method instead of a class field. When the server resolves the reference, it will invoke the annotated setter method with the result of the lookup. Listing 3-12 revisits Listing 3-9 one more time to demonstrate using setter injection.

Listing 3-12.  Using Setter Injection

@Stateless
public class DeptService {
    private AuditService audit;

    @EJB
    public void setAuditService(AuditService audit) {
        this.audit = audit;
    }

    // ...
}

This style of injection allows for private fields, yet also works well with unit testing. Each test can simply instantiate the bean class and manually perform the dependency injection by invoking the setter method, usually by providing an implementation of the required resource that is tailored to the test.

Declaring Dependencies

The following sections describe some of the resource annotations described in the Java EE specification. Each annotation has a name attribute for optionally specifying the reference name for the dependency. Other attributes on the annotations are specific to the type of resource that needs to be acquired.

Referencing a Persistence Context

In the previous chapter, we demonstrated how to create an entity manager for a persistence context using an EntityManagerFactory returned from the Persistence class. In the Java EE environment, the @PersistenceContext annotation can be used to declare a dependency on a persistence context and have the entity manager for that persistence context acquired automatically.

Listing 3-13 demonstrates using the @PersistenceContext annotation to acquire an entity manager through dependency injection into a stateless session bean. The unitName element specifies the name of the persistence unit on which the persistence context will be based.

image Tip  If the unitName element is omitted, it is vendor-specific how the unit name for the persistence context is determined. Some vendors can provide a default value if there is only one persistence unit for an application, whereas others might require that the unit name be specified in a vendor-specific configuration file.

Listing 3-13.  Injecting an EntityManager Instance

@Stateless
public class EmployeeService {
    @PersistenceContext(unitName="EmployeeService")
    EntityManager em;

    // ...
}

You might be wondering why a state field exists in a stateless session bean; after all, entity managers must maintain their own state to be able to manage a specific persistence context. The good news is that the specification was designed with container integration in mind, so what actually gets injected in Listing 3-13 is not an entity manager instance like the ones we used in the previous chapter. The value injected into the bean is a container-managed proxy that acquires and releases persistence contexts on behalf of the application code. This is a powerful feature of the Java Persistence API in Java EE and is covered extensively in Chapter 6. For now, it is safe to assume that the injected value will “do the right thing.” It does not have to be disposed of and works automatically with the transaction management of the application server. Other containers that support JPA, such as Spring, will offer similar functionality but they will generally require some additional configuration for it to work.

Referencing a Persistence Unit

The EntityManagerFactory for a persistence unit can be referenced using the @PersistenceUnit annotation. Like the @PersistenceContext annotation, the unitName element identifies the persistence unit for the EntityManagerFactory instance we want to access. If the persistent unit name is not specified in the annotation, it is vendor-specific how the name is determined.

Listing 3-14 demonstrates injection of an EntityManagerFactory instance into a stateful session bean. The bean then creates an EntityManager instance from the factory during the PostConstruct lifecycle callback. An injected EntityManagerFactory instance can be safely stored on any component instance. It is thread-safe and does not need to be disposed of when the bean instance is removed.

Listing 3-14.  Injecting an EntityManagerFactory Instance

@Stateful
public class EmployeeService {
    @PersistenceUnit(unitName="EmployeeService")
    private EntityManagerFactory emf;
    private EntityManager em;

    @PostConstruct
    public void init() {
        em = emf.createEntityManager();
    }

    // ...
}

The EntityManagerFactory for a persistence unit is not used as often in the Java EE environment because injected entity managers are easier to acquire and use. As you will see in Chapter 6, there are important differences between the entity managers returned from the factory and the ones provided by the server in response to the @PersistenceContext annotation.

Referencing Server Resources

The @Resource annotation is the catchall reference for Java EE resource types that don’t have dedicated annotations. It is used to define references to resource factories, data sources, and other server resources. The @Resource annotation is also the simplest to define because the only additional element is resourceType, which allows you to specify the type of resource if the server can’t figure it out automatically. For example, if the field you are injecting into is of type Object, then there is no way for the server to know that you wanted a data source instead. The resourceType element can be set to javax.sql.DataSource to make the need explicit.

One of the features of the @Resource annotation is that it is used to acquire logical resources specific to the component type. This includes EJBContext implementations as well as services such as the EJB timer service. Without defining it as such, we used setter injection to acquire the EJBContext instance in Listing 3-10. To make that example complete, the @Resource annotation could have been placed on the setSessionContext()method. Listing 3-15 revisits the example from Listing 3-10, this time demonstrating field injection with @Resource to acquire a SessionContext instance.

Listing 3-15.  Injecting a SessionContext Instance

@Stateless
@EJB(name="audit", beanInterface=AuditService.class)
public class DeptService {
    @Resource
    SessionContext context;
    AuditService audit;

    @PostConstruct
    public void init() {
        audit = (AuditService) context.lookup("audit");
    }

    // ...
}

CDI and Contextual Injection

While the basic platform injection facilities are helpful, they are clearly limited both in terms of what can be injected and how much control can be exerted over the injection process. CDI provides a more powerful injection standard that first extends the notion of a managed bean and platform resource injection and then goes on to define a set of additional injection services available to beans managed by CDI. Of course, the key characteristic of contextual injection is the ability to inject a given object instance according to the currently active context.

The capabilities of CDI are broad and extensive, and obviously well beyond the scope of a book on JPA. For the purposes of this book we'll only scratch the surface and show how to create and use simple CDI beans with qualifiers. We suggest that interested readers refer to some of the many books written about CDI to find out more about interceptors, decorators, events, and the many other features available within a CDI container.

CDI Beans

One of the benefits of EJBs is that it provides all of the services that one might need, from security to automatic transaction management and concurrency control. However, the full service model can be seen as a drawback if you don’t use or want some of the services, since the perception is that there is at least some cost associated with having them. Managed beans, and the CDI extensions to them, provide more of a pay-as-you-go model. You only get the services that you specify. Don't be fooled, though, into thinking that CDI beans are any less bulky than a modern EJB. When it comes down to implementation, both types of objects are proxied by the container in pretty much the same way and the service hooks will be added in and triggered as necessary.

What are CDI beans, anyway? A CDI bean is any class that qualifies for the CDI injection services, the primary requirement of which is simply that it be a concrete class.2 Even session beans can be CDI beans and thus qualify for CDI injection services, although there are some caveats about their lifecycle contexts.

Injection and Resolution

A bean may have its fields or properties be the target of injection if they are annotated by @javax.inject.Inject. CDI defines a sophisticated algorithm for resolving the correct type of object to inject, but in the general case, if you have a field declared of type X, then an instance of X will be injected into it. We can rewrite the example in Listing 3-10 to use simple managed CDI beans instead of EJBs. Listing 3-16 shows the use of the injection annotation on a field. The AuditService instance will get injected after the DeptService instance gets instantiated.

Listing 3-16.  CDI Bean with Field Injection

public class DeptService {
    @Inject AuditService audit;

    // ...
}

The annotation could similarly be placed on a property method to employ setter injection. Yet another way to achieve the same result is to use a third kind of injection called constructor injection. As the name suggests, constructor injection involves the container invoking the constructor method and injecting the arguments. Listing 3-17 shows how constructor injection can be configured. Constructor injection is particularly good for testing outside of the container since a test framework can easily do the necessary injection by simply calling the constructor without having to proxy the object.

Listing 3-17.  CDI Bean with Constructor Injection

public class DeptService {
    private AuditService audit;

    @Inject DeptService(AuditService audit) {
        this.audit = audit;
    }
    // ...
}

Scopes and Contexts

A scope defines a pair of temporal demarcation points: a beginning and an end. For example, a request scope would begin when the request starts and end when the reply has been sent back. Similarly, other scopes define durations based upon client actions and conditions. There are five pre-defined scopes, three of which (request, session, and application) are defined by the servlet specification, one more (conversation) that was added by CDI, and another that was added by the JTA spec:

  1. Request: Delineated by a specific client method request.
  2. Session: Starts on initiation from an HTTP client and ends upon the termination of the HTTP session. Shared by all requests in the same HTTP session.
  3. Application: Global to the entire application for as long as it is active.
  4. Conversation: Spans a series of sequential JSF requests.
  5. Transaction: Maps to the lifetime of an active JTA transaction.

A bean type is associated with a scope by annotating the bean class with the intended scope annotation. Managed instances of that bean will have a lifecycle similar to the declared scope.

Each scope that is active will have a current context associated with it. For example, when a request arrives, a request context will be created for that request scope. Each request will have its own current request context, but there will be a single session scoped context for all of the requests coming from the same HTTP session. The context is just the place where the scoped instances reside for the duration of the scope. There can be only one instance of each bean type in each context.

The application scoped AuditService bean that would be injected into the DeptService bean in Listings 3-16 or 3-17 would look like the following:

@ApplicationScoped
public class AuditService { ... }

Because it is application scoped, only a single instance would be created by CDI and reside in the application scoped context. Note that this is similar to a singleton EJB in that only a single instance would be created and used by the entire application.

An additional scope, dependent, also exists, but is really the absence of scope. If no scope is specified, then the dependent scope is assumed, meaning that no instances of the bean are put into any context and a new instance is created each time an injection of that bean type occurs. The @Dependent annotation can be used to explicitly mark a bean as being dependent. Scope annotations are defined in the javax.enterprise.context package.

image Tip  A beans.xml descriptor was required in CDI 1.0. In CDI 1.1, beans may instead be annotated with a bean-defining annotation (i.e., a scope annotation) to preclude the beans.xml descriptor from being required. In the examples that use CDI, we will make use of scope annotations to avoid having to specify a beans.xml file.

Qualified Injection

A qualifier is an annotation that is used to constrain or distinguish a bean type from other bean types that have the same inherited or implemented interface type. A qualifier can help the container resolve which bean type to inject.

The qualifier annotation class is typically defined by the application and then used to annotate one or more bean classes. The qualifier annotation definition should be annotated with the @Qualifier meta-annotation, defined in the javax.inject package. An example of defining a qualifier annotation is in Listing 3-18.

Listing 3-18.  Qualifier Annotation Definition

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

This annotation can now be used on a bean class, such as the new SecureDeptService bean shown in Listing 3-19. The qualifier indicates that the bean is a secure variety of DeptService, as opposed to a regular (non-secure?) one.

Listing 3-19.  Qualified Bean Class

@Secure
public class SecureDeptService extends DeptService { ... }

When a DeptService is to be injected into another component, the qualifier can be placed at the injection site and CDI will activate its resolution algorithm to determine which instance to create. It will match the qualifiers to use the SecureDeptService instead of DeptService. Listing 3-20 shows how a servlet, for example, might inject a secure DeptService without even having to know the name of the subclass.

Listing 3-20.  Qualified Injection

public class LoginServlet extends HttpServlet {

    @Inject @Secure DeptService deptService ;
    // ...
}

Producer Methods and Fields

When the container needs to inject an instance of a bean type, it will first look in the current contexts to see if one already exists. If it does not find one, then it must obtain or create a new instance. CDI provides a way for the application to control the instance that gets "created" for a given type by using a producer method or field.

A producer method is a method that the CDI container will invoke to obtain a new bean instance. The instance may be instantiated by the producer method or the producer may obtain it through some other means; it is entirely up to the implementation of the producer method how it produces the instance. Producer methods may even decide based on runtime conditions to return a different bean subclass.

A producer method can be annotated with a qualifier. Then when an injection site is similarly qualified, the container will call that correspondingly qualified producer method to obtain the instance.

In Listing 3-21, we show a producer method that returns new secure instances of DeptService. This might be useful, for example, if we were not able to modify the SecureDeptService class to annotate it with the @Secure annotation as we did in Listing 3-19. We could instead declare a producer method that returned instances of SecureDeptService and they would be injected into fields qualified with @Secure (such as the one shown in Listing 3-20). Note that a producer method may be on any managed bean. It may be a static or instance method, but it must be annotated with @Produces. We have created a bean class named ProducerMethods to hold the producer method and separate it from the rest of the application logic.

Listing 3-21.  Producer Method

public class ProducerMethods {

    @Produces @Secure
    DeptService secureDeptServiceProducer() {
        return new SecureDeptService();
    }
}

Producer fields work the same way as producer methods except that the container accesses the field to get the instance instead of invoking a method. It is up to the application to ensure that the field contains an instance when the container needs it. You will see an example of using a producer field in the next section.

Using Producer Methods with JPA Resources

Now that you know some of the basics of CDI, it's time to learn how CDI can be used to help manage JPA persistence units and contexts. You can use a combination of Java EE resource injection with CDI producer fields and qualifiers to inject and maintain your persistence contexts.

Let's assume we have two persistence units, one named "Employee" and the other named "Audit". We want to use CDI beans and contextual injection. We will create a class named EmProducers and use producer fields and Java EE resource injection to obtain the entity managers. The producer code and qualifier annotation definitions are in Listing 3-22.

Listing 3-22.  Producer Class and Qualifier Annotation Definitions

@RequestScoped
public class EmProducers {

    @Produces @EmployeeEM
    @PersistenceContext(unitName="Employee")
    private EntityManager em1;

    @Produces @AuditEM
    @PersistenceContext(unitName="Audit")
    private EntityManager em2;

}

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

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

The Java EE @PersistenceContext annotation will cause the Java EE container to inject the producer fields with the entity manager for the given persistence unit. The producer fields will then be used by CDI to obtain the entity manager with the matching qualifier of the injection site. Because the producer class is request scoped, new entity managers will be used for each request. The appropriate scope will obviously depend upon the application architecture. The only thing left to do is to have a bean that is injected with these entity managers. A corresponding DeptService bean that references the entity managers is shown in Listing 3-23. A same approach could just as easily be used to inject an entity manager factory using the @PersistenceUnit resource annotation.

Listing 3-23.  DeptService Bean with Injected EntityManager Fields

public class DeptService {

    @Inject @EmployeeEM
    private EntityManager empEM;

    @Inject @AuditEM
    private EntityManager auditEM;

    // ...
}

In the majority of our examples we will simply use the @PersistenceContext annotation since it does not involve any additional producer code. It is also supported by Spring and other kinds of JPA containers, so the bean will be more generic.

Transaction Management

More than any other type of enterprise application, applications that use persistence require careful attention to issues of transaction management. When transactions start, when they end, and how the entity manager participates in container-managed transactions are all essential topics for developers using JPA. The following sections will lay out the foundation for transactions in Java EE; we will revisit this topic in detail again in Chapter 6 as we look at the entity manager and how it participates in transactions. Advanced transaction topics are beyond the scope of this book. We recommend Java Transaction Processing3 for an in-depth discussion on using and implementing transactions in Java, and Principles of Transaction Processing4 for a look at transactions and transaction systems in general.

Transaction Review

A transaction is an abstraction that is used to group together a series of operations. Once grouped together, the set of operations is treated as a single unit, and all of the operations must succeed or none of them can succeed. The consequence of only some of the operations being successful is to produce an inconsistent view of the data that will be harmful or undesirable to the application. The term used to describe whether the operations succeed together or not at all is called atomicity, and it is arguably the most important of the four basic properties that are used to characterize how transactions behave. Understanding these four properties is fundamental to understanding transactions. The following list summarizes these properties:

  • Atomicity: Either all the operations in a transaction are successful or none of them are. The success of every individual operation is tied to the success of the entire group.
  • Consistency: The resulting state at the end of the transaction adheres to a set of rules that define acceptability of the data. The data in the entire system is legal or valid with respect to the rest of the data in the system.
  • Isolation: Changes made within a transaction are visible only to the transaction that is making the changes. Once a transaction commits the changes, they are atomically visible to other transactions.
  • Durability: The changes made within a transaction endure beyond the completion of the transaction.

A transaction that meets all these requirements is said to be an ACID transaction (the familiar ACID term being obtained by combining the first letter of each of the four properties).

Not all transactions are ACID transactions, and those that are often offer some flexibility in the fulfillment of the ACID properties. For example, the isolation level is a common setting that can be configured to provide either looser or tighter degrees of isolation than what was described earlier. They are typically done for reasons of either increased performance or, on the other side of the spectrum, if an application has more stringent data consistency requirements. The transactions that we discuss in the context of Java EE are normally of the ACID variety.

Enterprise Transactions in Java

Transactions actually exist at different levels within the enterprise application server. The lowest and most basic transaction is at the level of the resource, which in our discussion is assumed to be a relational database fronted by a DataSource interface. This is called a resource-local transaction and is equivalent to a database transaction. These types of transactions are manipulated by interacting directly with the JDBC DataSource that is obtained from the application server. Resource-local transactions are used less frequently in servers than container transactions.

The broader container transaction uses the Java Transaction API (JTA) that is available in every compliant Java EE application server and most of the Java-based web servers. This is the typical transaction that is used for enterprise applications and can involve or enlist a number of resources, including data sources as well as other types of transactional resources. Resources defined using Java Connector Architecture (JCA) components can also be enlisted in the container transaction.

Containers typically add their own layer on top of the JDBC DataSource to perform functions such as connection management and pooling that make more efficient use of the resources and provide a seamless integration with the transaction management system. This is also necessary because it is the responsibility of the container to perform the commit or rollback operation on the data source when the container transaction completes.

Because container transactions use JTA and because they can span multiple resources, they are also called JTA transactions or global transactions. The container transaction is a central aspect of programming within Java servers.

Transaction Demarcation

Every transaction has a beginning and an end. Beginning a transaction will allow subsequent operations to become a part of the same transaction until the transaction has completed. Transactions can be completed in one of two ways. They can be committed, causing all of the changes to be persisted to the data store, or rolled back, indicating that the changes should be discarded. The act of causing a transaction to either begin or complete is termed transaction demarcation. This is a critical part of writing enterprise applications, because doing transaction demarcation incorrectly is one of the most common sources of performance degradation.

Resource-local transactions are always demarcated explicitly by the application, whereas container transactions can either be demarcated automatically by the container or by using a JTA interface that supports application-controlled demarcation. The first case, when the container takes over the responsibility of transaction demarcation, is called container-managed transaction (CMT) management, but when the application is responsible for demarcation, it's called bean-managed transaction (BMT) management.

EJBs can use either container-managed transactions or bean-managed transactions. Servlets are limited to the somewhat poorly named bean-managed transaction. The default transaction management style for an EJB component is container-managed. To explicitly configure an EJB to have its transactions demarcated one way or the other, the @TransactionManagement annotation should be specified on the EJB class. The TransactionManagementType enumerated type defines BEAN for bean-managed transactions and CONTAINER for container-managed transactions. Listing 3-24 demonstrates how to enable bean-managed transactions using this approach.

Listing 3-24.  Changing the Transaction Management Type of an EJB

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class ProjectService {
    // methods in this class manually control transaction demarcation
}

image Note  Because the default transaction management for an EJB is container-managed, the @TransactionManagement annotation needs to be specified only if bean-managed transactions are desired.

Container-managed Transactions

The most common way to demarcate transactions is to use CMTs, which spare the application the effort and code to begin and commit transactions explicitly.

Transaction requirements are determined by metadata and are configurable at the granularity of the class or even a method. For example, a session bean can declare that whenever any specific method on that bean gets invoked, the container must ensure that a transaction is started before the method begins. The container is also responsible for committing the transaction after the completion of the method.

It is quite common for one bean to invoke another bean from one or more of its methods. In this case, a transaction started by the calling method will not have been committed because the calling method will not be completed until its call to the second bean has completed. This is why we need settings to define how the container should behave when a method is invoked within a specific transactional context.

For example, if a transaction is already in progress when a method is called, the container might be expected to just make use of that transaction, whereas it might be directed to start a new one if no transaction is active. These settings are called transaction attributes, and they determinethe container-managed transactional behavior.

The defined transaction attribute choices are as follows:

  • MANDATORY: If this attribute is specified for a method, a transaction is expected to have already been started and be active when the method is called. If no transaction is active, an exception is thrown. This attribute is seldom used, but can be a development tool to catch transaction demarcation errors when it is expected that a transaction should already have been started.
  • REQUIRED: This attribute is the most common case in which a method is expected to be in a transaction. The container provides a guarantee that a transaction is active for the method. If one is already active, it is used; if one does not exist, a new transaction is created for the method execution.
  • REQUIRES_NEW: This attribute is used when the method always needs to be in its own transaction; that is, the method should be committed or rolled back independently of methods further up the call stack. It should be used with caution because it can lead to excessive transaction overhead.
  • SUPPORTS: Methods marked with supports are not dependent on a transaction, but will tolerate running inside one if it exists. This is an indicator that no transactional resources are accessed in the method.
  • NOT_SUPPORTED: A method marked to not support transactions will cause the container to suspend the current transaction if one is active when the method is called. It implies that the method does not perform transactional operations, but might fail in other ways that could undesirably affect the outcome of a transaction. This is not a commonly used attribute.
  • NEVER: A method marked to never support transactions will cause the container to throw an exception if a transaction is active when the method is called. This attribute is very seldom used, but can be a development tool to catch transaction demarcation errors when it is expected that transactions should already have been completed.

Any time the container starts a transaction for a method, the container is assumed to also attempt to commit the transaction at the end of the method. Each time the current transaction must be suspended, the container is responsible for resuming the suspended transaction at the conclusion of the method.

There are actually two different ways of specifying container-managed transactions, one for EJBs and one for CDI beans, servlets, JAX-RS resource classes, and all other types of Java EE managed components. EJBs were the first component type to offer a container-managed transaction feature and defined specific metadata for the purpose. CDI beans and other types of Java EE components, such as servlets or JAX-RS resource classes, make use of a transactional interceptor.

EJB Container-managed Transactions

The transaction attribute for an EJB can be indicated by annotating the EJB class, or one of its methods that is part of the optional business interface, with the @TransactionAttribute annotation. This annotation requires a single argument of the enumerated type TransactionAttributeType, the values of which are defined in the preceding list. Annotating the bean class will cause the transaction attribute to apply to all of the business methods in the class, whereas annotating a method applies the attribute only to the method. If both class-level and method-level annotations exist, the method-level annotation takes precedence. In the absence of class-level or method-level @TransactionAttribute annotations, the default attribute of REQUIRED will be applied.

Listing 3-25 shows how the addItem()method from the shopping cart bean in Listing 3-5 might use a transaction attribute. No transaction management setting was supplied, so container-managed transactions will be used. No attribute was specified on the class, so the default behavior of REQUIRED will apply to all the methods of the class. The exception is that the addItem() method has declared a transaction attribute of SUPPORTS, which overrides the REQUIRED setting. Whenever a call to add an item is made, that item will be added to the cart, but if no transaction was active none will need to be started.

Listing 3-25.  Specifying an EJB Transaction Attribute

@Stateful
public class ShoppingCart {

    @TransactionAttribute(TransactionAttributeType.SUPPORTS)
    public void addItem(String item, Integer quantity) {
        verifyItem(item, quantity);
        // ...
    }

    // ...
}

Furthermore, before the addItem() method adds the item to the cart, it does some validation in a private method called verifyItem() that is not shown in the example. When this method is invoked from addItem(), it will run in whatever transactional context addItem() was invoked.

Any bean wanting to cause a container-managed transaction to roll back can do so by invoking the setRollbackOnly() method on the EJBContext object. Although this will not cause the immediate rollback of the transaction, it is an indication to the container that the transaction should be rolled back when the transaction completes. Note that entity managers will also cause the current transaction to be set to roll back when an exception is thrown during an entity manager invocation or when the transaction completes.

Transactional Interceptors

When interceptors were introduced to the Java EE 6 platform, they opened up the future possibility of decoupling the container-managed transaction facility from EJB and offering it to any component that supported interception. In Java EE 7, the @javax.transaction.Transactional annotation was added as a means to specify that a transactional interceptor would be applied to the target component. The mechanism acts similarly to EJB container-managed transactions in that it is declaratively applied on a class or method and a class semantic can be overridden by a method-based one. The main difference is that the @Transactional annotation is used instead of @TransactionAttribute, and the type of the enumerated value is a nested enum called Transactional.TxType instead of the TransactionAttributeType used in EJB. The enum constants in the list above are named exactly the same in Transactional.TxType and have the same semantics.

Perhaps the most relevant difference between transactional interceptor-based components and EJB CMT is the fact that the components that use transactional interceptors do not automatically get CMT but must opt in by using the @Transactional annotation. EJBs get CMT by default and must opt out if they prefer to use BMT.

We can now rewrite Listing 3-25 to use a CDI bean instead of a stateful session bean. The ShoppingCart bean in Listing 3-26 is session scoped so that its state is maintained throughout the session. The empty @Transactional annotation causes the default transactionality to be set to REQUIRED for all of the methods in the class, except for the addItem() method that is explicitly overridden to be SUPPORTS.

Listing 3-26.  Transactional Interceptor in a CDI Bean

@Transactional
@SessionScoped
public class ShoppingCart {

    @Transactional(TxType.SUPPORTS)
    public void addItem(String item, Integer quantity) {
        verifyItem(item, quantity);
        // ...
    }

    // ...
}

image Tip  @Transactional can be used on managed beans or CDI beans but may not be used on EJBs. Conversely, @TransactionAttribute can only be used on EJBs.

Bean-managed Transactions

Another way of demarcating transactions is to use BMTs. This just means that the application needs to start and stop transactions explicitly by making API calls. With the exception of EJBs, all managed components default to using bean-managed transactions and are left to do their own transaction demarcation if they don’t specify the @Transactional interceptor. Only EJBs are provided container-managed transactions by default.

Declaring that an EJB is using bean-managed transactions means that the bean class is assuming the responsibility to begin and commit the transactions whenever it deems it is necessary. With this responsibility, however, comes the expectation that the bean class will get it right. EJBs that use BMT must ensure that any time a transaction has been started, it must also be completed before returning from the method that started it. Failure to do so will result in the container rolling back the transaction automatically and an exception being thrown.

One penalty of transactions being managed by the EJBs instead of by the container is that they do not get propagated to methods called on another BMT EJB. For example, if EJB A begins a transaction and then calls EJB B, which is using bean-managed transactions, the transaction will not get propagated to the method in EJB B. Any time a transaction is active when a BMT EJB method is invoked, the active transaction will be suspended until control returns to the calling method. This is not true for non-EJB components.

BMT is not generally recommended for use in EJBs because it adds complexity to the application and requires the application to do work that the server can already do for it. While other types of components can use transactional interceptors if they choose, they do not have the same BMT restrictions that EJBs have, so it is more common for them to adopt an application-controlled BMT approach. They have also traditionally used BMT because there was never really a choice in the past. It was only recently, in Java EE 7, that transaction interceptors were introduced.

UserTransaction

For a component to be able to manually begin and commit container transactions, the application must have an interface that supports it. The javax.transaction.UserTransaction interface is the designated object in JTA that application components can hold on to and invoke to manage transaction boundaries. An instance of UserTransaction is not actually the current transaction instance; it is a sort of proxy that provides the transaction API and represents the current transaction. A UserTransaction instance can be injected into components by using either of the Java EE @Resource or CDI @Inject annotations. A UserTransaction is also present in the environment naming context under the reserved name “java:comp/UserTransaction”. The UserTransaction interface is shown in Listing 3-27.

Listing 3-27.  The UserTransaction Interface

public interface UserTransaction {
    public abstract void begin();
    public abstract void commit();
    public abstract int getStatus();
    public abstract void rollback();
    public abstract void setRollbackOnly();
    public abstract void setTransactionTimeout(int seconds);
}

Each JTA transaction is associated with an execution thread, so it follows that no more than one transaction can be active at any given time. So if one transaction is active, the user cannot start another one in the same thread until the first one has committed or rolled back. Alternatively, the transaction can time out, causing the transaction to roll back.

We discussed earlier that in certain CMT conditions the container will suspend the current transaction. From the previous API, you can see that there is no UserTransaction method for suspending a transaction. Only the container can do this using an internal transaction management API. In this way, multiple transactions can be associated with a single thread, even though only one can ever be active at a time.

Rollbacks can occur in several different scenarios. The setRollbackOnly() method indicates that the current transaction cannot be committed, leaving rollback as the only possible outcome. The transaction can be rolled back immediately by calling the rollback() method. Alternately, a time limit for the transaction can be set with the setTransactionTimeout() method, causing the transaction to roll back when the limit is reached. The only catch with transaction timeouts is that the time limit must be set before the transaction starts and it cannot be changed once the transaction is in progress.

In JTA, every thread has a transactional status that can be accessed through the getStatus() call. The return value of this method is one of the constants defined on the javax.transaction.Status interface. If no transaction is active, for example, then the value returned by getStatus() will be the STATUS_NO_TRANSACTION. Likewise, if setRollbackOnly() has been called on the current transaction, then the status will be STATUS_MARKED_ROLLBACK until the transaction has begun rolling back.

Listing 3-28 shows a fragment from a servlet using the ProjectService bean to demonstrate using UserTransaction to invoke multiple EJB methods within a single transaction. The doPost() method uses the UserTransaction instance injected with the @Resource annotation to start and commit a transaction. Note the try ... catch block required around the transaction operations to ensure that the transaction is correctly cleaned up in the event of a failure. We catch the exception and then rethrow it within a runtime exception after we perform the rollback.

Listing 3-28.  Using the UserTransaction Interface

public class ProjectServlet extends HttpServlet {
    @Resource UserTransaction tx;
    @EJB ProjectService bean;

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        // ...

        try {
            tx.begin();
            bean.assignEmployeeToProject(projectId, empId);
            bean.updateProjectStatistics();
            tx.commit();
        } catch (Exception e) {
            // Try to roll back (may fail if exception came from begin() or commit(), but that's ok)
            try { tx.rollback(); } catch (Exception e2) {}
            throw new MyRuntimeException(e);
        }

        // ...
    }
}

Putting It All Together

Now that we have discussed the application component model and services available as part of a Java EE application server, we can revisit the EmployeeService example from the previous chapter and bring it to the Java EE environment. Along the way, we’ll provide example code to show how the components fit together and how they relate back to the Java SE example.

Defining the Component

To begin, let’s consider the definition of the EmployeeService class from Listing 2-9 in Chapter 2. The goal of this class is to provide business operations related to the maintenance of employee data. In doing so, it encapsulates all the persistence operations. To introduce this class into the Java EE environment, we must first decide how it should be represented. The service pattern exhibited by the class suggests a session bean or similar component. Because the business methods of the bean have no dependency on each other, we can further decide that any stateless bean, such as a stateless session bean, is suitable. In fact, this bean demonstrates a very typical design pattern called a session façade5, in which a stateless session bean is used to shield clients from dealing with a particular persistence API. To turn the EmployeeService class into a stateless session bean we need only annotate it with @Stateless.

In the Java SE example, the EmployeeService class must create and maintain its own entity manager instance. We can replace this logic with dependency injection to acquire the entity manager automatically. Having decided on a stateless session bean and dependency injection, the converted stateless session bean is demonstrated in Listing 3-29. With the exception of how the entity manager is acquired, the rest of the class is identical. This is an important feature of the Java Persistence API because the same EntityManager interface can be used both inside and outside of the application server.

Listing 3-29.  The EmployeeService Session Bean

@Stateless
public class EmployeeService {
    @PersistenceContext(unitName="EmployeeService")
    protected EntityManager em;

    EntityManager getEntityManager() {
        return em;
    }

    public Employee createEmployee(int id, String name, long salary) {
        Employee emp = new Employee(id);
        emp.setName(name);
        emp.setSalary(salary);
        getEntityManager().persist(emp);
        return emp;
    }

    public void removeEmployee(int id) {
        Employee emp = findEmployee(id);
        if (emp != null) {
            getEntityManager().remove(emp);
        }
    }

    public Employee changeEmployeeSalary(int id, long newSalary) {
        Employee emp = findEmployee(id);
        if (emp != null) {
            emp.setSalary(newSalary);
        }
        return emp;
    }

    public Employee findEmployee(int id) {
        return getEntityManager().find(Employee.class, id);
    }

    public List<Employee> findAllEmployees() {
        TypedQuery query = getEntityManager().createQuery("SELECT e FROM Employee e", Employee.class);
        return query.getResultList();
    }
}

Defining the User Interface

The next question to consider is how the bean will be accessed. A web interface is a common presentation method for enterprise applications. To demonstrate how this stateless session bean might be used by a servlet, consider Listing 3-30. The request parameters are interpreted to determine the action, which is then carried out by invoking methods on the injected EmployeeService bean. Although only the first action is described, you can see how this could easily be extended to handle each of the operations defined on EmployeeService.

Listing 3-30.  Using the EmployeeService Session Bean from a Servlet

public class EmployeeServlet extends HttpServlet {
    @EJB EmployeeService bean;

    protected void doPost(HttpServletRequest request,
                          HttpServletResponse response) {
        String action = request.getParameter("action");

        if (action.equals("create")) {
            String id = request.getParameter("id");
            String name = request.getParameter("name");
            String salary = request.getParameter("salary");
            bean.createEmployee(Integer.parseInt(id), name,
                                Long.parseLong(salary));
        }

        // ...
    }
}

Packaging It Up

In the Java EE environment, many properties required in the persistence.xml file for Java SE can be omitted. In Listing 3-31, you see the persistence.xml file from Listing 2-11 converted for deployment as part of a Java EE application. Instead of JDBC properties for creating a connection, we now declare that the entity manager should use the data source name “jdbc/EmployeeDS”. If the data source was defined to be available in the application namespace instead of the local component naming context, then we might instead use the data source name of “java:app/jdbc/EmployeeDS”. The transaction-type attribute has also been removed to allow the persistence unit to default to JTA. The application server will automatically find entity classes, so even the list of classes has been removed. This example represents the ideal minimum Java EE configuration.

Because the business logic that uses this persistence unit is implemented in a stateless session bean, the persistence.xml file would typically be located in the META-INF directory of the corresponding EJB JAR, or the WEB-INF/classes/META-INF directory of the WAR. We will fully describe the persistence.xml file and its placement within a Java EE application in Chapter 14.

Listing 3-31.  Defining a Persistence Unit in Java EE

<persistence>
    <persistence-unit name="EmployeeService">
        <jta-data-source>jdbc/EmployeeDS</jta-data-source>
    </persistence-unit>
</persistence>

Summary

It would be impossible to provide details on all of the features of the Java EE platform in a single chapter. However, we cannot put JPA in context without explaining the application server environment in which it will be used. To this end, we introduced the technologies that are of the most relevance to the developer using persistence in enterprise applications.

We began with an introduction to enterprise software components and introduced the EJB component model. We argued that the use of components is more important than ever before and identified some of the benefits that come from leveraging them. We introduced the fundamentals of stateless, stateful, and singleton session beans and showed the syntax for declaring them as well as the difference in interaction style between them.

We next looked at dependency management in Java EE application servers. We discussed the reference annotation types and how to declare them. We also looked at the difference between dependency lookup and dependency injection. In the case of injection, we looked at the difference between field and setter injection. We then explored each of the resource types, demonstrating how to acquire and inject server and JPA resources.

Building on the foundation of Java EE resource injection, we went on to introduce the CDI model with its generalized notion of a managed bean. We listed the predefined scopes and explained the contexts that CDI uses to cache the contextual instances it injects. We showed how qualifiers can contribute additional constraints to the injection resolution process and how producers can be defined to return the instances the CDI container uses for injection. We then demonstrated a way to use producers to inject qualified persistence resources.

In the section on transaction management, we looked at JTA and its role in building data-centric applications. We then looked at the difference between bean-managed transactions and container-managed transactions for EJBs and non-EJBs. We documented the different types of transaction attributes for CMT beans and showed how to manually control bean-managed transactions.

We concluded the chapter by exploring how to use Java EE components with JPA by converting the example application introduced in the previous chapter from a command-line Java SE application to a web-based application running in an application server.

Now that we have introduced JPA in both the Java SE and Java EE environments, it’s time to dive into the specification in detail. In the next chapter we begin this journey with the central focus of JPA: object-relational mapping.

1 All annotations used in this chapter are defined in the javax.ejb, javax.inject, javax.enterprise.inject or javax.annotation packages.

2 Non-static inner classes excluded.

3 Little, Mark, Jon Maron, and Greg Pavlik. Java Transaction Processing: Design and Implementation. Upper Saddle River, N.J.: Prentice Hall PTR, 2004.

4 Bernstein, Philip A., and Eric Newcomer. Principles of Transaction Processing. Burlington, MA: Morgan Kaufmann, 2009.

5 Alur et al., Core J2EE Patterns.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.245.196