分享

[Bernstein09] 10.4. Java Enterprise Edition

 Stefen 2010-06-24

10.4. Java Enterprise Edition

Java Enterprise Edition (Java EE) refers to an umbrella specification that groups 79 API specifications (as of Java EE 5) designed for enterprise computing applications such as transaction processing. Java EE API features work together to provide a complete environment for developing and deploying TP applications, including:

  • The Swing Library, Servlets, Java Server Pages, and Java Server Faces for developing front-end programs, including interactive menu and forms capabilities for web browsers and native PC and UNIX programs

  • Enterprise Java Beans (EJBs), a distributed computing component model for developing request controllers and transaction servers that support a variety of front-end programs

  • The Java Persistence API (JPA), a lightweight object-relational mapping integrated with EJBs to interact with persistent entities stored in a relational database

  • The Java Connector Architecture (JCA) API, a programming environment for integration with legacy systems that includes a standard client and adapter toolkit

  • The Java Transaction API (JTA), an infrastructure and programming environment for transaction management, used in both the implicit and explicit programming models for Java EE

  • A WS-BPEL engine for business process management, which is also provided by most Java EE vendors

Java EE is defined through the Java Community Process, a consortium of Java vendors chaired by Sun Microsystems. Java EE originally was released in December 1999, and has gone through several iterations since then. Its original name was Java 2 Enterprise Edition, or J2EE, which was changed to Java EE as of its fourth release, called Java EE 5. A major difference between the enterprise edition and the standard edition of Java is the addition of EJBs. The current version, EJB3, represents a significant change from earlier versions of EJB (1.1 through 2.1), with a lighter weight container, JPA in place of entity beans, and the use of Java 5 annotations for transaction demarcation and other EJB functions.

Java EE APIs are delivered in Java-EE-compliant application server products from IBM, Oracle, Red Hat, and others. Java-EE-compliant vendors must pass a set of conformance tests to receive a certification from the Java Community Process, which indicates that the vendor has successfully implemented each of the required APIs. Examples of certified products include IBM’s WebSphere Application Server, Oracle’s WebLogic Application Server, and Red Hat’s JBoss Application Server. These products are available on UNIX, Windows, and zOS operating systems. Java-EE-compliant application servers typically include vendor-specific mechanisms for server clustering and failover, sometimes including state caching and replication. However, these features are not included in the Java EE APIs and are therefore beyond the scope of this book.

In contrast to the Microsoft transactional middleware, which runs only on Windows operating systems, Java-based transactional middleware runs on virtually any operating system. But operating system portability has its costs. In particular, .NET Framework components are generally better integrated with the operating system than Java-based components. As might be expected, the specific details of how to create and deploy transactional programs with Java EE and the .NET Framework are different, even though the technologies and underlying concepts are very similar.

Figure 10.15 illustrates the relationships among the transactional middleware components of the Java EE architecture. It includes two types of front-end programs, those designed to run in a web browser and those designed to run on a desktop PC or UNIX system. The Java EE architecture is very similar to the .NET Framework in this respect, but a significant difference is the presence of EJBs, which are programs and associated containers that were specifically designed for use in TP applications.

Figure 10.15. Java EE Multitier Transactional Middleware Architecture. The components of the Java EE environment provide several options for developing and deploying front-end programs, request controllers, and transaction servers.

Typically, a browser-based front-end program communicates with the web tier, which in turn calls the EJB tier. The EJB tier then invokes one or more JPA entities at the persistence tier. An EJB may also use JCA to invoke a back-end system, such as a legacy TP monitor, or may directly access a database using SQL commands through Java Database Connectivity (JDBC).

The standard protocol for remote communication between the web tier and the EJB tier is the Java Remote Method Invocation over the CORBA Internet Inter-Orb Protocol (RMI/IIOP). Other communication protocols can also be used. SOAP over HTTP is supported from a Web Services client to the EJB tier. Java EE vendors typically offer proprietary communications protocols and data formats specifically tuned for their individual products. It is also fairly common practice for the web tier to communicate locally with the EJB tier.

An application developed using Java-EE-compliant transactional middleware components can therefore implement a two-tier, three-tier, or multitier architecture to meet scalability, availability, and other TP application requirements. For example:

  • When a web browser is used for the front-end program, a web server can function as the request controller by including an EJB that routes the request to a transaction server program.

  • When a PC- or UNIX-based front-end program is used, the EJB tier can be used to fulfill the request controller function on its own, without a web server.

  • When multiple tiers are needed, EJBs can be used to fulfill both the request controller and transaction server functions (including the persistence tier).

  • Stored procedures can also fulfill the transaction server function for web server hosted or plain EJB-based request controllers.

As in the .NET environment, both implicit and explicit transaction programming models are supported, and the implicit model is recommended for most applications.

Developing Front-End Programs

In Java EE the technologies used for front-end programs include:

  • The Swing Library for PC- and UNIX-based GUIs

  • Servlets, Java Server Pages (JSP), and Java Server Faces (JSF) for web browser-based GUIs

Swing is the name of a collection of libraries and functions used to develop highly interactive PC- and UNIX-based front-end programs. The Swing Library is comparable to the .NET Framework’s WPF and Silverlight. Library functions define a screen’s area and layout, menus, scroll bars, tabs, buttons, sliders, tables, frames, toolbars, and so on. The example in Figure 10.16 uses the Swing libraries to display a table of information. As shown in the figure, Swing classes can be used to construct a variety of GUI features. In this case the JTable class is used to create a table of a customer’s accounts. Although the main program thread exits at the end of the example, Swing supplies a second thread that continues processing in the background to handle GUI components.

Figure 10.16. Code for a Java Swing-Based Table. The Swing client displays a list of accounts and balances for a customer.
import java.awt.*;
import javax.swing.*;

public class SimpleTable extends JFrame {
public SimpleTable() {
super("Transfer");
setSize(300, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
JTable jt = new JTable(
new String[][] {
{"John Smith", "Savings", "100.0"} },
new String[] { "Customer", "Account", "Balance"}
);
JScrollPane scp = new JScrollPane(jt);
getContentPane().add(scp, BorderLayout.CENTER);
}

public static void main(String args[]) {
SimpleTable st = new SimpleTable();
st.setVisible(true);
}
}

A Java servlet extends the capability of a standard web server to support dynamic content generation. The Java Servlet API is an alternative to web server callout mechanisms such as Common Gateway Interface (CGI) scripts and web server APIs such as Apache API or ISAPI (IIS). Servlets handle HTTP sessions and route requests to Java objects, EJBs, or databases. Servlets also handle REST and Web Services communications. The server can use any technique to maintain session state, typically using cookies or URL rewriting. All Java-EE-based application server products include a servlet engine. Apache Tomcat is an example of a popular standalone servlet engine.

Java Server Pages (JSP) layer on servlets and replace static HTML and XML pages with dynamic content generated using JSP tags embedded in HTML or XML pages. The tags access and generate content that is then formatted into HTML or XML. When the page request is executed, a JSP is converted to a servlet for handling the content to be displayed in the browser.

The example in Figure 10.17 illustrates the use of JSP tags to generate information within an HTML bulleted list. When executed, the JSP tags dynamically generate the content for the bank name, the account balance, and the current date of the web server access. Java Server Faces (JSF) components are server-side controllers of browser-based menu and form components such as buttons, tables, and graphics. JSF and JSP technologies can work together, for example when JSFs are used to create JSPs, and JSPs generate content for JSF-defined menu and form elements. JSPs and JSFs can work in combination to drive server-side and client-side user interaction scenarios. For example, the JSF custom library can be used by the JSP to generate content and GUI elements for the browser.

Figure 10.17. JSP Tags Generate Content for an HTML List. JSP 2.0 tags inside an HTML list include an expression that finds the web bank’s name, an account balance, and a directive that gets and displays the current date.
<UL>
<LI> Web Bank name: ${account.bankName}
<LI> Current Balance: ${account.balance}
<LI><B> JSP 1.2 expression: </B><BR>
Current date: <%= new java.util.Date()%>
</UL>

The example in Figure 10.18 illustrates a simple form defined using JSF tag libraries. The JSF component classes maintain the component’s state and the rendering tags define how to render the content for the user. For example, the commandButton tag is rendered as a button. The example also illustrates a validation function to check a username when the button is clicked. When a JSP is created using JSF, a tree of components is mapped into memory from which a response to a browser request is generated.

Figure 10.18. JSF Components Prompt for a Username and Create a Submit Button. This JSF component prompts the user for his or her name and checks it with the server-side username validation program.
<%@ taglib uri="http://java./jsf/html" prefix="h" %>
<%@ taglib uri="http://java./jsf/core" prefix="f" %>
<body bgcolor="white">
<f:view>
<h:form id="Sign In Form">
<h2>Username:</h2>
<h:inputText id="username" value="#{UserNameBean.userName}"
validator="#{UserNameBean.validate}"/>
<h:commandButton id="submit" action="success" value="Submit"/>
</h:form>
</f:view>

REST Support

REST support in Java EE environments is provided by the Java API for Restful Web Services (JAX-RS). JAX-RS defines a set of annotations and interfaces that can be used in Java objects to expose them as RESTful web resources. JAX-RS objects can be deployed to either a standalone servlet engine or a servlet engine within a Java EE application server. JAX-RS enables front-end programs to call the objects using HTTP as the network protocol, using HTTP content types to define the data formats.

Developing Request Controllers and Transaction Servers

An Enterprise Java Bean (EJB) refers both to a type of Java program designed for TP applications and to a container within which such a program is deployed. An EJB abstracts transactional middleware functionality, such as threading, transaction control, and security. EJBs originally were designed for compatibility with legacy TP monitors, although the most popular implementations of EJBs have been written from scratch. EJBs have evolved significantly from their initial definition. Compared to EJB2, EJB3 beans feature a lighter weight container, dependency injection, and Java 5 attributes for expressing configuration properties.

In Java EE, a request controller can be developed for the web tier or the EJB tier. When developed for the web tier, the request controller typically is implemented using a servlet engine running inside a web server, which routes the request to an EJB. The EJB can execute in the web server or in a separate process.

EJB types include:

  • Session beans: Designed for hosting an interactive session with the front-end program. A session bean can be stateless or stateful and can manage transactions.

  • Message-driven beans: Designed for interacting with asynchronous messaging systems that conform to the Java Messaging Service (JMS) API.

EJB2 defined a third EJB type, an entity bean. Entity beans are preserved in EJB3 for compatibility with EJB2 applications. In EJB3, entity beans are replaced by JPA entities (covered next and in Section 10.6).

An EJB can manage transactions and participate in transactional compositions. A message-driven bean can also manage transactions, but cannot be composed into a transaction started by another bean.

A session bean is allocated to a single instance of a front-end program and is terminated when the front-end program terminates. A stateful session bean maintains the state of its instance variables for the duration of its interaction with the front-end program; a stateless session bean does not.

Stateful session bean state is volatile and not transactional. For a web browser front-end program, session state management also can be provided by the HttpSession object. For PC- or UNIX-based Swing clients stateful session beans are the only mechanism available to preserve in-memory conversational state across multiple interactions between the front-end program and the request controller.

As with any stateless design, the advantage of a stateless session bean is that the application server can maintain a reusable pool of stateless session beans, allocate them to any request on demand, and deallocate them once a bean finishes executing the request. With a stateful bean the application server has to direct a subsequent call by a given front-end program to the same bean instance so that it has access to the state of its conversation with the front end.

A stateless session bean can have a Web Service interface, allowing a Web Service client to invoke an EJB method. Web Services support is included in the Java EE specifications through the inclusion of the Java API for XML-Based Web Services (JAX-WS) specification. Therefore, all Java-EE-complaint application server products offer toolkits that generate a Web Service interface from an EJB interface.

A session bean can query and update a relational database by using one or more JPA entities. The data members of a JPA entity are transactionally persistent, and a session bean can access that state by issuing operations on the JPA EntityManager. Like a web server, however, a session bean also has the option to access a database directly to execute embedded SQL or to invoke a stored procedure using JDBC. Direct database access is commonly used in practice.

A bean implementation class is an ordinary Java class file that contains the method implementations for the EJB. An implementation class exposes a business interface for remote and local access to business logic methods. Restrictions on the Java class and methods used for an EJB ensure that everything works correctly when deployed within a container, such that they must be public, cannot be final, and cannot be abstract.

A bean implementation class becomes an EJB by importing one or more EJB libraries and either including one or more EJB annotations or declaring it an EJB in an associated descriptor file (see Figure 10.24). EJB annotations control the abstractions of the container and generate deployment metadata. As of EJB3 the embedded annotations can be used to generate the descriptor file. As with entity beans, a manually coded descriptor file (i.e., created without using annotations) is supported for backward compatibility with EJB2. In EJB3, the embedded annotations typically are used to generate the deployment metadata, including any vendor-specific variations.

The EJB type annotations are:

  • @javax.ejb.Stateless

  • @javax.ejb.Stateful

  • @javax.ejb.MessageDriven

The first two define a session bean as being either stateless or stateful. The third defines a message-driven bean (i.e., one that interacts with JMS message queues). The Stateless annotation is more commonly used than Stateful. In EJB3, the @javax.ejb.entity annotation is used only to include an EJB 2.1 entity bean into an EJB3-compliant application server.

Other annotations specify transaction control, security, and how to handle messages and resources. Each of the annotations other than the EJB type has a default value if not specified. For example, if a transaction control annotation is not specified, the default is to require a transaction for each method in a class.

The example in Figure 10.19 illustrates a stateless session bean for a group of methods that can perform several operations for a fictitious bank account management application. A session bean typically is invoked by the servlet engine, although it can also be invoked using a Web Service, another EJB, or a Swing client. Since no @TransactionAttribute annotation is included, the bean uses default of container-managed transactions with a transaction required for the execution of each method. Thus, if a method is called from another method, the calling method’s transaction will be used. Otherwise a new transaction will be created.

Figure 10.19. Stateless Session Bean. This stateless EJB implements the operations of the AccountOperation interface to check a customer’s account balance and to withdraw or deposit funds.
import javax.ejb.Stateless;

@Stateless
public class AccountOperationBean implements AccountOperation {

public double balance(int accountNumber) {
Account acct = this.getAccount(accountNumber);
return acct.getBalance();
}

public void deposit(int accountNumber, double amount) {
Account acct = this.getAccount(accountNumber);
acct.setBalance(acct.getBalance() + amount);
}

public void withdraw(int accountNumber, double amount) {
Account acct = this.getAccount(accountNumber);
if (acct.getBalance() < amount) {
throw new InsufficientFundsException();
}
acct.setBalance(acct.getBalance() - amount);
}

private Account getAccount(int accountNumber) {
// Code to retrieve the Account balance
}
}


An EJB reference is needed to invoke a bean, with the exception of a Web Service invocation of a stateless session bean method. The EJB reference can be injected or retrieved using a directory lookup. A typical directory service for a Java EE-based application server is the Java Naming and Directory Interface (JNDI). Figure 10.20 shows an example of a client with an EJB reference injected using the @EJB annotation to provide the reference that can be used to invoke the Transfer EJB. The @Resource annotation also can be used to inject a variety of other external information, such an environment variable, an EJB context, a JMS destination, a connection factory, or a data source.

Figure 10.20. Sample EJB Reference for Transfer Class. An EJB reference can be injected to allow a front-end program or request controller to invoke an EJB.
import javax.naming.Context;
import javax.naming.InitialContext;

public class TransferClient
{
public static void main(String [] args)
{
@EJB Transfer myTransfer;
myTransfer.transfer(123, 456, 100.00);
}
}

The default for accessing an interface is local access; that is, from an EJB client running in the same address space. A remotely accessible interface needs to be explicitly identified using the @javax.ejb.Remote annotation. The @javax.ejb.Local annotation explicitly restricts an interface to local access.

The @TransactionManagement annotation defines whether the implicit or explicit programming model is used for a bean. Valid values for this attribute are:

  • TransactionManagementType.CONTAINER

  • TransactionManagementType.BEAN

When the value is CONTAINER the implicit programming model is used, which is called container managed in EJB terminology. When it’s BEAN, the explicit programming model is used, called bean managed.

The @javax.ejb.ApplicationException annotation marks an application exception that can be thrown by a method in a bean managed transaction. The exception is reported directly to the EJB client when it occurs. The rollback attribute of the annotation can be used to define whether the exception automatically causes a rollback.

The @TransactionAttribute is used to control the operations of the implicit programming model, such as whether or not the container is required to start a new transaction before executing each method in the class. The next section lists the valid values for this attribute.

A JPA entity can be defined within an EJB to map its data to a relational database, using an object-relational mapping. The @javax.persistence.Entity annotation defines a Java class as a JPA entity. A JPA entity can be used from within a session bean or a plain Java class.

In previous versions of EJB this functionality was called bean-managed or container-managed persistence. JPA is lighter weight, easier to use, and more efficient than the previous EJB approach. A JPA entity maps the data items and attributes of a Java class to one or more rows in one or more database tables. Optional attributes can be used to specify fine-grained control over which data items are persisted.

The example in Figure 10.21 shows a stateless session bean that uses a JPA EntityManager to create a new account record. Bean methods access and update the persistent resource. Operations to create or update an entity should execute in the context of a transaction, which is why the @TransactionAttribute annotation is set to REQUIRED. It creates a new Account record based on parameters passed to the createAccount method, and then calls the em.persist method to add a row to the database table. When used in an EJB, a JPA entity participates in the global transaction managed by the Java Transaction API (JTA; described later in this section). When used outside of an EJB, a JPA entity can use a JDBC managed transaction or a global transaction managed by JTA.

Figure 10.21. Using a JPA Entity to Create an Account Record. A JPA entity manager retrieves and updates persistent items in a database.
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.persistence.PersistenceContext;
import javax.persistence.EntityManager;
...

@Stateless
@TransactionAttribute(REQUIRED)
public class AccountCreationBean implements AccountCreation {
@PersistenceContext(unitName="AccountSystem")
private EntityManager em;
public void createAccount(String customerName, int accountNumber,
double initialDeposit) {
Account acct = new Account(accountNumber);
acct.setCustomerName(customerName);
acct.setBalance(initialDeposit);
em.persist(acct);
}
}

Transaction Management in Java

Java developers creating TP applications may choose to use a persistence abstraction from a plain Java object or from within an EJB. If using a plain Java object, a session can be established with a single resource manager to directly control its transactions. If using a persistence abstraction within an EJB, JTA is used to control the transaction.

An EJB does not have an equivalent mechanism to the .NET Framework set.complete() method because an EJB is not treated as a transaction participant. Nor does the EJB specification include a concept directly comparable to an ambient transaction; that is, one that exists independently of the lifecycle of an object for which a transaction is started. However, Java EE does offer the setRollbackOnly command for a subobject to tell the top-level object to abort.

The Implicit Programming Model

In the implicit programming model the EJB container automatically starts and terminates a transaction when a transactional EJB method is invoked. Successful completion commits the transaction and an exception can be set to cause an automatic abort.

By default, the EJB container automatically invokes a business method within a transaction context and automatically decides whether to commit or abort the transaction, depending on whether the method completes successfully or not. A transaction annotation can be specified on the entire bean class, or on individual methods to override the default behavior. An annotation at the method level overrides an annotation at the class level, if both are specified.

Valid values for the @TransactionAttribute annotation are:

  • REQUIRES_NEW

  • REQUIRED

  • SUPPORTS

  • NOT_SUPPORTED

  • MANDATORY

  • NEVER

The transaction attribute values instruct the container to perform the following operations:

  • REQUIRES_NEW. Every invocation of the method starts executing in a new transaction, whether or not the caller was already executing in a transaction.

  • REQUIRED. If the caller is already running within a transaction, then the called method executes within that transaction. If not, then the called method starts executing in a new transaction.

  • SUPPORTS. If the caller is already running within a transaction, then the called method executes within that transaction. If not, then the called method does not execute within a transaction.

  • NOT_SUPPORTED. The called method does not execute within a transaction, even if the caller is running within a transaction.

  • MANDATORY. If the caller is already running within a transaction, then the called method executes within that transaction. If not, an exception is raised.

  • NEVER. If the caller is already running within a transaction, an exception is raised.

If the transaction attribute of a message-driven bean is REQUIRED, then the bean executes as a top-level transaction. The transaction includes its operations on the message queue and on any other transactional resources. Operations in a message-driven bean cannot join the transactional operations of any other bean. When the transaction attribute is NOT_SUPPORTED, the message-driven bean’s operations do not execute in the context of a transaction. A container-managed transaction is required to coordinate operations on message queues with operations on other persistent resources.

An EJB always uses JTA unless the NOT_SUPPORTED attribute is specified. JTA implementations use a one-phase commit optimization whenever there’s a single resource manager. This optimization is sufficient for most applications. However, unlike the PSPE optimization in .NET’s system.transactions, it still involves the application server’s transaction manager. There are workarounds, but they involve the EJB doing explicit transaction control with the RM.

Figure 10.22 illustrates a session bean that uses the REQUIRED attribute to invoke two methods within the same transaction. The REQUIRED attribute means that if the caller is executing in a transaction, then any called methods also execute within the caller’s transaction. If the caller is not executing a transaction, the method executes in a new top-level transaction.

Figure 10.22. Transactional Session Bean Invoking Two Methods. Both the Withdraw and Deposit methods are invoked within the same transaction.
public class TransferBean implements Transfer {
@EJB AccountOperation op;
...
@TransactionAttribute(REQUIRED)
public void transfer(int acct1, int acct2, double amount) {
op.withdraw(acct1, amount);
op.deposit(acct2, amount);
}
}

An exception class can be defined so that when the execution of a transaction throws an exception, the application can catch it in the exception handler and throw an application-specific exception. In the example in Figure 10.23 the @ApplicationException annotation sets the rollback attribute to true, meaning that when the exception handler catches an exception of the defined type, a TransferException is raised, and a rollback is signaled for the transaction.

Figure 10.23. Using a Try Block to Catch an Exception. The try block allows an exception to be caught and transferred for the transaction.
>>> Exception class:
import javax.ejb.ApplicationException;
@ApplicationException(rollback = true)
public class TransferException extends RuntimeException {}

>>> Session bean class:
import javax.ejb.*;
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class TransferBean implements Transfer {

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void transfer(int acct1, int acct2, double amount) {
try {
<<do transfer>>
} catch (Exception e1) {
<<log>>
throw new TransferException(e1);
}
}
}

Transaction control attributes can be specified either as embedded annotations and attributes in EJB3 or in a deployment descriptor file, which is illustrated in Figure 10.24. A descriptor file can be either hand-coded or generated from annotations and attributes. For each EJB listed in the example file, the implicit programming model is specified ( transaction-type is container) and a transaction control attribute is associated with either all methods of a class (using an asterisk) or with a particular method of the class (for example, transfer).

Figure 10.24. Using an EJB Deployment Descriptor to Specify Transaction Control Attributes. The EJB descriptor file associates EJB method names with attributes that define whether the program in the bean uses the explicit or implicit programming model, and whether or not a transaction context is required to invoke the method.
<ejb-jar>
...
<session>
<ejb-name>AccountOperationBean</ejb-name>
...
<transaction-type>Container</transaction-type>
</session>
<session>
<ejb-name>TransferBean</ejb-name>
...
<transaction-type>Container</transaction-type>
</session>

<assembly-descriptor>
...
<container-transaction>
<method>
<ejb-name>AccountOperationBean</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>

<container-transaction>
<method>
<ejb-name>TransferBean</ejb-name>
<method-name>transfer</method-name>
</method>
<trans-attribute>RequiresNew</trans-attribute>
</container-transaction>

</assembly-descriptor>
</ejb-jar>


The Explicit Programming Model

In the Java EE environment, explicit transaction programming directly uses the Java Transaction API (JTA) in a bean-managed transaction. JTA has three major functional areas:

  • Simple transaction demarcation: javax.transaction.UserTransaction

  • Transaction manger control: javax.transaction.TransactionManager

  • A Java mapping of the XA API for resource integration: javax.transaction.xa.XAResource

The UserTransaction part of the API is used for bean managed transactions; that is, for explicit transaction programming in an EJB. The TransactionManager part of the API typically is used by application server vendors to access and control the functions of an independent transaction manager, such as a Java Transaction Service (JTS) compliant transaction manager. Some application server products explicitly prohibit its use. The XAResource portion of the API is a Java mapping of the standard XA interface that the application server uses to include XA-compliant resource managers into JTA-managed transactions.

The underlying implementation of JTA isn’t explicitly defined and may vary from vendor to vendor. JTS specifies one implementation, using the Object Management Group’s Object Transaction Service (OTS, described in Section 10.8) and General Inter-ORB Protocol (IIOP). Vendors typically use a combination of JTS and XA-compliant libraries. Transaction interoperability between transactional Java EE application servers is optional, but if supported it must use JTS/OTS.

JTA can be used in a Java EE environment. It can also be used outside a Java EE environment when an independent implementation of JTA is available, such as Atomikos or the JBoss Transaction Manager.

Figure 10.25 illustrates the use of explicit transaction management within a stateless session bean. The UserTransaction part of the JTA API is used in a stateless EJB to start ( utx.begin()) and terminate ( utx.commit()) a transaction. A transaction has to be started and completed in the same method, although the transaction context (as in the implicit model) can be propagated to other methods. As shown in the example, an exception handler can be defined to issue the utx.rollback()command and throw an exception to the client if there’s a problem.

Figure 10.25. Explicit Transaction Control in a Stateless Session Bean. A stateless session bean can explicitly manage a transaction that includes updates to multiple resource managers.
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class TransferBean implements Transfer {

@Resource private UserTransaction utx;

public void transfer(int acct1, int acct2, double amount) {
try {
utx.begin();
<<do transfer>>
utx.commit();
} catch (Exception e1) {
try { utx.rollback(); } catch (Exception e2) {}
<<log>>
throw new TransferException(e1);
}
}

Integration with Legacy TP Monitors

The Java Connector Architecture (JCA) defines a standard way for Java-EE-compliant transactional middleware to connect to legacy TP monitors and other existing systems such as packaged applications. JCA provides a set of APIs and system programming interfaces for developing and deploying connections and adapters to existing systems. JCA can propagate a transaction context from an EJB to a legacy TP monitor, depending on the compatibility of the application server’s and legacy TP monitor’s transaction protocols.

JCA defines a set of system-level contracts between a Java EE application server and an existing system. They include contracts for communications, security, and transaction management. JCA defines a common client interface that allows an EJB to call an adapter written for an existing technology’s external client or a custom-developed adapter. It can propagate application server features using one or more connection contracts, such as one that propagates transaction context. JCA calls such a contract a resource adapter. A resource adapter plugs into the application server as a protocol and functional bridge between an application server and an existing system.

Transaction management is integrated with JTA and is based on wrapping each existing transactional environment as an XA resource so it can be coordinated using the application server’s transaction manager. JCA offers the application server the option to delegate transaction management to the local resource when a single resource manager is involved in the transaction, saving the overhead of two-phase commit coordination when it isn’t needed. Transaction propagation works with both the implicit and explicit programming models.

Existing systems such as legacy TP monitors typically support external clients, for example ECI for CICS and TP Web Connector for ACMS. Vendors also have the option of providing their own JCA-compliant adapter. JCA adapters are capable of bidirectional communication, including transactions, between existing systems and application servers.

Spring Transactions

The Spring Framework is a popular open source programming model for developing enterprise applications, such as TP applications, using plain old Java objects (POJOs) and EJBs. Spring objects, called Spring Beans, can be deployed into Java-EE-compliant application servers, standalone servlet engines that don’t support EJBs, or OSGi Frameworks such as Eclipse Equinox and Apache Felix.

The Spring Framework offers a widely-adopted lightweight alternative to EJBs, including transactional middleware functions. Spring works with popular EJB containers and standalone JTA-compliant transaction managers such as the JBoss Transaction Manager, the Atomikos transaction manager, or the Java Open Transaction Manager (JOTM) from the OW2 Consortium. The Spring Framework extends transaction processing applications outside of the Java-EE-compliant application server environment and offers a lightweight alternative for single resource transactions.

Spring supports two models for transaction management:

  • Local: Delegates transaction management to the persistence abstraction mechanism (e.g., JDBC or JPA)

  • JTA: Uses the JTA API from within the Spring Platform Transaction Manager API explicitly to initiate and terminate transactions

Spring supports both implicit and explicit programming models for either the local or JTA transaction management models. The implicit and explicit models are called declarative and programmatic demarcation, respectively. Declarative demarcation uses embedded annotations whereas programmatic demarcation uses the JTA API. Spring Beans using transactions can be deployed within an EJB container or independently of an EJB container as long as the requisite transaction management infrastructure is available (i.e., a transactional persistence abstraction mechanism and/or a standalone JTA implementation).

Spring transaction management uses the Spring Platform Transaction Manager API to abstract the transaction management and programming models. The local and JTA transaction management models are strategies. A transaction management strategy is defined or altered using a configuration file associated with a Spring Bean. The Spring Framework focuses primarily on local transaction management as the most common use of two-phase commit; that is, coordinating transactional resources that reside on the same machine.

The Spring Framework supports local propagation of transaction context across method invocations using either strategy. Remote propagation of transaction context uses a JTA-aware communication protocol (e.g., RMI and RMI/IIOP) and requires explicit JTA programming.

The Spring Framework allows TP application developers to define which exceptions will cause a rollback, a capability that is also available in EJB3.

As shown in Figure 10.26, the Spring Framework uses the PlatformTransactionManager interface to implement the transaction strategy declared for a Spring Bean. The strategy can choose a transaction manager that provides a JTA API, or it can use the transaction management capabilities of a JDBC connection. However, it is also possible for a Java programmer to use this interface directly from a Spring Bean to programmatically set the strategy.

Figure 10.26. The Spring Framework Abstract Interface for Transaction Management. The interface is used internally by the Spring Framework to set the transaction strategy, which is defined in an associated configuration file. It can also be used explicitly by developers to control the transaction strategy programmatically.
public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition definition)
throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}

In Figure 10.27 the PROPAGATION_REQUIRED attribute is set to ensure that the method is invoked within a transaction context. Note that remote context propagation requires the use of the explicit programming model. The example also illustrates the way in which the Spring Framework allows a rollback to be associated with an application defined exception, such as MyException.

Figure 10.27. Using the Spring Framework for Explicit Transaction Management. A new transaction is defined for the Transfer method along with its propagation behavior. The transaction is initiated and completed within the try block, which also can throw the rollback exception.
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setName("Transfer");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

TransactionStatus status = txManager.getTransaction(def);
try {
//execute your business logic here
}
catch (MyException ex) {
txManager.rollback(status);
throw ex;
}
txManager.commit(status);

The implicit model implements declarative demarcation using Spring’s @Transactional annotation. This works similarly to EJB’s annotation system. Spring supports the EJB @TransactionAttribute values and extends them for defining a custom isolation level or a read-only transaction, or to control cache flushing.

In the example in Figure 10.28, the @Transactional annotation indicates using the Propagation.REQUIRES_NEW property that a new transaction must be started before executing the withdrawFunds method, even when a transaction context is propagated on the method invocation. Spring supports EJB propagation options and adds a NESTED option to support nested transactions. This can be used by persistence abstraction mechanisms that support savepoints, such as a JDBC3 driver or Apache OpenJPA.

Figure 10.28. Spring Transactions Implicit Model. Spring uses the @Transactional annotation to declaratively specify transaction control for a method (method code not shown).
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void withdrawFunds(Account Amount) {
...
}

Switching the transaction management strategy from local to JTA is accomplished using a configuration change. For example, the first part of Figure 10.29 configures the local Spring transaction management strategy to use a JDBC driver and the second part configures a JTA strategy. A configuration change to a JTA strategy may be necessary when a Spring Bean accesses multiple resource managers within the same transaction, or needs to propagate transaction context remotely.

Figure 10.29. Switching Transaction Strategies. Spring transactions use configuration to switch transaction management strategies.
<tx:annotation-driven/>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myTargetDataSourceBean"/>
</bean>
<tx:annotation-driven/>

<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager"/>

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多