Resource Adapter (RA)
The resource adapter (RA) is a system library that provides connectivity to an EIS system. The RA is the heart of the J2EE Connector Architecture and interacts with all the participants, that is, with the application server and the application component, as well as with the EIS system. Given its prime role in the JCA architecture, it is not surprising to note that the RA implements both the system contracts and the application contracts specified in the JCA specification.
EIS vendors must create RAs that comply with the JCA specification to be deemed Java Connector Architecture compliant. The RA implements the CCI. This makes the RA the black box behind the CCI. When a Java program uses an interface in the CCI, it is calling a component in the RA that implements that interface. This allows for a pluggable, component-based approach to solving Java-EIS integration.
The RA is where all the system-level functionality is achieved. The Java application and the EIS communicate with each other indirectly through the RA. The adapter translates requests from the Java application into calls on the EIS.
The system contracts define the interaction between the application server and the RA. The system contracts relate to the core functionalities required during the interaction for accessing EIS resources such as connectivity, transactions, and security.
RAs are the JCA equivalent of the JDBC drivers that you learned about earlier but on an enterprise scale. A JDBC driver enables client applications and application servers to interact with databases seamlessly. Similarly, an RA enables enterprise applications and application servers to interact with different EIS systems seamlessly.
System contracts in JCA are the predefined set of responsibilities that each participant in the contract must fulfill to enable seamless integration and interaction.
In Figure 21.4 you can see that JCA defines the following set of design contracts between an application server and an RA for an EIS:
Figure 21.4. Application server design contracts—EIS.
In future versions of JCA, the contracts will extend support for asynchronous messaging (Java Messaging Service).
Next you'll look at each system contract.
Connection Management Contract
The connection management contract is a set of consistent interfaces that an EIS resource adapter must provide for interaction between an application server and its components (in a managed environment) or interaction between an application server and a standalone application (in a nonmanaged environment). The contract clearly identifies the responsibilities of implementation of the EIS RA vendor and the application server vendor.
As a part of the connection management contract, the following features are available:
From Figure 21.5 you can see that the participants in the contract are the resource adapter, the application server, and the application components. Following are details about the features the participants must provide to fulfill their obligations for the connection management contract.
Figure 21.5. Application server–resource adapter—connection management contract.
Because it has interactions with the application server, the application component, and the EIS, the RA forms the heart of the contract. The RA will normally be implemented by an EIS vendor; the vendor is in the best position to supply the implementation of an interface to the EIS to provide services such as connectivity to the EIS, transaction handling, callbacks to managed environments, and so on.
The RA covers the following features of the connection management contract.
The interfaces used in a nonmanaged environment scenario by the application component for obtaining connections are these two:
The interfaces used in a managed environment scenario by the application server for obtaining connections are the following:
javax.resource.spi.ManagedConnectionFactory javax.resource.spi.ManagedConnection javax.resource.spi.ManagedConnectionMetaData
In a nonmanaged two-tier (client/server) environment scenario, the RA directly performs connection handling and related features for an application component for obtaining connections. Hence, it also provides its own implementation of the javax.resource.spi.ConnectionManager interface. This implementation provided by the RA is known as the default connection manager. The RA vendor provides the functionality behind these interfaces. The implementation is normally proprietary/specific to the EIS for which the adapter is provided.
In a managed environment, the RA does not provide connection pooling because the application server provides it. But in a nonmanaged environment it is the responsibility of the RA to implement this feature internally. This is normally done by the default connection manager.
Support for Application Server Features
In order to provide callbacks to an application server in a managed environment, the RA, in its implementation of the ManagedConnection interface, provides a mechanism for registering the connection event listener of the application server. In a nonmanaged environment, the RA provides some rudimentary error-logging facilities of its own, in the implementation of the ManagedConnectionFactory and the ManagedConnection interfaces. This is done via the following methods:
javax.resource.spi.ManagedConnectionFactory.setLogWriter() javax.resource.spi.ManagedConnectionFactory.getLogWriter() javax.resource.spi.ManagedConnection.setLogWriter() javax.resource.spi.ManagedConnection.setLogWriter()
Support for Transaction Management
Support for transaction management will be covered in the section on transaction management contracts.
Support for Security Management
Support for security management will be covered in the section on security management contracts.
The application server provides application components, executing within its environment the necessary interface to enterprise resources. This application server interacts with the resource adapter to provide services such as connection pooling, transaction management, error logging, security management, and so on for application components. The vendor of an application server provides the implementation of the interfaces with the resource adapter. Application components residing and executing within an application server are referred to as applications executing in a managed environment.
The application server forms the basis for the managed environment scenario. Hence, all the following contract features relate only to this scenario:
The application server uses the interfaces provided by the RA for acquiring connections (see the previous section on acquiring connections). Because all the functionality related to managing the connection obtained from the RA is the responsibility of the application server, it provides implementation of the javax.resource.spi.ConnectionManager interface. This implementation is used by the RA's javax.resource.cci.ConnectionFactory implementation to delegate a connection request from an application component in a managed environment scenario.
In a managed environment, the application server provides connection pooling. This is done by the ConnectionManager implementation.
Support for Application Server Features
Because the responsibility of implementing the connection-acquiring and error-logging functionality lies with the RA, the application server does not provide its own mechanisms. But in order to receive callbacks from the RA, the application server provides implementation of the javax.resource.spi.ConnectionEventListener interface. The listener implementation of this interface is registered with the RA (using the RA's ManagedConnection implementation) thus, enabling the application server to receive event notifications from the RA. The implementation of the ConnectionEventListener also provides mechanisms for local transaction management (which will be covered in the next section).
An enterprise application developer can use the Common Client Interfaces in application components to interact with the RA. These application components can be either beans (deployed in application servers) or standalone classes/applications. Depending on how they are used, the application components can be said to be executing in a managed or nonmanaged environment.
From the set of participants in the connection management contract, you can see that for a developer, the application component is essentially the consumer in the contract, and the RA and application server form the provider of services. For an enterprise developer, writing an application component in a managed or nonmanaged environment will involve using the Common Client Interface (CCI). The APIs involved will be these:
As seen previously, the RA provides the implementation of these interfaces. Apart from this, the application component may use interfaces from the transaction management and security management contract as required.
Transaction Management Contract
Transactional access for resources is a concept that already has been elaborated and supported by J2EE specification. In the context of JCA, it assumes more significance because the applications designed for using JCA access EIS resources, which may or may not support transactions inherently (legacy systems).
Transactions in JCA can either span multiple enterprise systems or can be local to the EIS. To support all of these transactions, JCA defines the transaction management contract. The transaction management contract is a well-defined set of interfaces between an application server and an RA.
The transaction management contract extends the connection management contract because transactions operate on resources, which, in this case, are connections to the EIS. The transaction management contract defines support for the following interfaces:
As you see in Figure 21.6, the participants in the transaction management contract are the RA, the application server, and the application components. These participants have certain responsibilities to fulfill.
Figure 21.6. Application server–resource adapter—transaction management contract.
The RA is the major participant in this contract because it interacts directly with the EIS. It provides support for both the JTA-XA and local types of contracts.
As there is no interaction with the transaction manager, there are no additional methods required, as in the case of the previous mechanism.
Relationship of the Transaction Management and Connection Management Contracts
Because transactions deal with EIS connections as the resources, look at how these are related in JCA. As per the connection management contract, the RA provides implementation of the javax.resource.spi.ManagedConnection interface to enable the application server to obtain connections to the underlying EIS. The javax.resource.spi.ManagedConnection.getLocalTransaction() method of this interface returns the reference of the javax.resource.spi.LocalTransaction object. The application server enlists this reference with its transaction manager, thereby providing an application component with the means for transaction processing on this resource, using the methods discussed previously.
The scenarios stated previously hold true for managed environments. But what about the nonmanaged environment applications? As you learned earlier, application components in a nonmanaged environment can obtain EIS connection via the RA using the CCI. So what transaction support does the RA provide for this?
For local transaction management in a nonmanaged environment, the RA provides the reference to the LocalTransaction object by implementing the methods of the javax.resource.cci.LocalTransaction interface. The methods in this interface are exactly the same in terms of name and signature as the methods for the managed environment. With this interface, an application component can perform transaction management without any transaction manager or application server.
The javax.resource.cci.LocalTransaction reference explained previously is totally different from the one for the managed environment (which is javax.resource.spi.LocalTransaction).
The application server is the consumer in this contract. Because an application server provides support for transaction management for its application components, it contains a transaction manager to handle this functionality.
The application server utilizes the transactional support provided by the RA as a part of the transaction management contract. The contract is required to support all three levels of transaction, namely XA (JTA), local, and No transaction:
The application component obtains a reference to the LocalTransaction object from the RA using the javax.resource.cci.Connection.getLocalTransaction() method implemented by the RA. With this it can perform transaction management programmatically by using the following RA-implemented methods:
javax.resource.cci.LocalTransaction.begin() javax.resource.cci.LocalTransaction.commit() javax.resource.cci.LocalTransaction.rollback()
Apart from implementing support for transaction management, the RA also provides a mechanism for callbacks of the state of the transactions. With this, a transaction manager, an application server, or an application component can obtain the state of the transaction being executed. The RA implements the following methods of the javax.resource.spi.ConnectionEventListener interface (seen earlier in the connection management contract):
The final system contract that will be covered today is the security contract.
Ensuring secure access of EIS resources is another aspect for which the JCA defines standard mechanisms. From defining a "sandbox" for executing applets to the security policy file concept in J2SE and J2EE, security has always been the focal point of the Java language. With JCA the security model encompasses security interfaces for EIS resources. The resources in EIS are essentially the connections used to access the EIS data. Hence, as with transactions, security and connections go hand in hand.
The security contract in JCA defines the obligations that an application server and resource adapter must fulfill for secure access of EIS resources. Because security is implicit with connection management, the security contract extends the connection management contract. The security contract in JCA utilizes the security architecture defined by Java Authentication and Authorization Services (JAAS), which were discussed on Day 19, "Using WebLogic Tools."
JAAS builds upon the existing security features in the security package of the Java Development Kit and defines an entire security architecture that is useful and suitable for enterprise applications. JCA leverages this security architecture in the decurity management contract and utilizes the API defined by JAAS.
Security Contract Participants
From Figure 21.7 you can see that, as was the case for the other types of contracts, the participants in the security contract are the RA, the application server, and the application component. These participants have the following responsibilities:
Figure 21.7. Application server–resource adapter—security contract.
The RA provides support for security features in its connection API implementation. Authentication in JCA can be either declarative or programmatic. These methods are also termed container-managed sign-on and component-managed sign-on. The RA supports both of these mechanisms as a part of the security contract.
For container-managed sign-on, the RA accepts security information from the application server using the javax.resource.spi.ManagedConnectionFactory.createManagedConnection() method. This method takes the javax.security.auth.Subject and the ConnectionRequestInfo objects as parameters. Because the security contract is based upon JAAS, the RA extracts the authentication information from the Subject and uses it to authenticate with the EIS. Any additional request-specific data is passed by the RA in the ConnectionRequestInfo.
For component-managed sign-on, the RA interacts with the application component via the CCI using the method javax.resource.cci.ConnectionFactory.getConnection(). This method takes the ConnectionSpec object as a parameter. The RA implements the ConnectionSpec interface to enable the application component developer to pass the security information using setter-getter methods.
The application server provides support for security for its application components using a security manager. The security manager within the application server also supports declarative security via deployment descriptors.
The application server supports declarative (that is, container-managed) sign-on using deployment descriptors. The key parameters used in the deployment descriptor file are:
Apart from this, the application server passes the security information in the deployment file to the RA by calling the method javax.resource.spi.ManagedConnectionFactory.createManagedConnection() with the javax.security.auth.Subject and ConnectionRequestInfo objects as parameters.
The application server populates the ManagedConnectionFactory object with security information such as user ID, password, and so on in the Subject. This security information is defined at deployment.
In a component-managed sign-on scenario, the application component interacts with the RA using the Common Client Interface (CCI) to pass the security information. It uses the javax.resource.cci.ConnectionFactory.getConnection() method, which takes the ConnectionSpec object as a parameter. The ConnectionSpec interface is implemented by the RA. It is used by the application component to pass the user ID, password, and any EIS-specific connection parameters (as required) to the RA. The implementation of this interface normally has accessor-mutator (that is, getter-setter) methods, enabling ease of use. A sample code snippet is given here:
// obtain a reference to the Connection Factory object from the JNDI javax.resource.cci.ConnectionFactory myConnFactory = ... // set the security properties in ConnectionSpec using "setter" methods javax.resource.cci.ConnectionSpec myConnectionProp = new myeis.ConnectionSpecImpl(); myConnectionProp.setUserName(); myConnectionProp.setPassword(); // Pass the ConnectionSpec object and obtain a connection from the // connection factory javax.resource.cci.Connection myConn = myConnFactory.getConnection(myConnectionProp); ...