Oracle Application Server 10g Migrating from WebSphere 10g (9.0.4) Part Number B10426-01 |
|
This chapter provides you with an overview of Sun Microsystems' Enterprise JavaBeans (EJB) architecture and its implementation in Oracle Application Server. In addition, the issues involved in migrating EJB components from WebSphere Advanced Edition 3.5.3 to Oracle Application Server are presented.
This chapter contains these topics:
Enterprise JavaBeans (EJB) is the standard server-side component architecture for developing and deploying object-oriented Java applications. It enables developers to quickly and easily build distributed applications.
A major goal of the EJB architecture is to provide component portability at both the source code level and the binary code level.
EJB components, called enterprise beans, are server-side components, written in Java, that typically contain the business logic of an application. The different types of enterprise beans are summarized in Table 5-1.
Although the EJB architecture does provide for component portability, certain implementation-specific aspects of an EJB component remain non-portable. These include:
One of the goals of the EJB initiative is to deliver component portability between different environments not only at source-code level, but also at a binary level, to ensure portability of compiled, packaged components. While it is true that EJB does offer an appreciable deal of portability, there are still a number of non-portable, implementation-specific aspects that need to be addressed when migrating components from one application server to another. Typically, an EJB component requires low-level interfaces with the container in the form of stubs and skeleton classes that will probably always need to be container implementation-specific. In effect, a clear partitioning between portable and non-portable elements of an EJB component can be drawn from the EJB 1.1 specification:
The following sections describe EJB specifications, session beans, and entity beans, transactions and concurrency, the WebSphere support for these APIs and WebSphere extensions, the difference between OC4J and WebSphere in the EJB containers and finally the migration path to OC4J.
In brief, the goal of EJB technology surpasses the basic Java object model by integrating new functionality important for enterprise systems:
From a developer's point of view, an EJB is presented as a group of files that brings together:
EJB servers manage low-level system resources, allocating resources to the containers as they are needed. The EJB Server hosts and provides a runtime environment for the EJB containers. Containers are transparent to the client--there is no client API to manipulate the container, and there is no way for a client to tell in which container an enterprise bean is deployed. However, the EJB container and the EJB servers are not clearly separated constructs. The EJB specification only defines a bean-container contract and does not define a container-server contract.
The EJB container is a specialized service in which enterprise beans are deployed. EJB containers insulate the deployed enterprise beans from the underlying EJB server and provide a standard application programming interface (API) between the beans and the container. This specialized service manages their life cycle, transactions, security, naming, persistence, and so on, according to a specific contract and constrained model delineated by the EJB specification. To do this, the container uses the generic services provided by the server.
The Enterprise JavaBeans specification identifies the following roles that are associated with a specific task in the development of distributed applications.
Typically an expert in the application domain; for example, in the financial or telecommunications industry. The bean provider implements the business task without being concerned about the distribution, transaction, security, and other non-business aspects of the application.
This is also a domain expert. The application assembler composes an application from various prefabricated building blocks (that is, enterprise beans) and adds other components such as GUI clients, applets, and servlets to complete the application. While composing an application, an assembler is only concerned with the interfaces to enterprise beans, but not with their implementation.
The deployer is specialized in the installation of applications. The deployer adapts an application, composed of a number of enterprise beans, to a target operation environment by modifying the properties of the enterprise beans. The deployer's tasks include, for example, the setting of transaction and security policies, specifying JNDI names by setting the appropriate properties in the deployment descriptor, and integration with enterprise management software.
Typically a vendor with expertise in distributed infrastructures and services. The server provider implements a platform, which facilitates the development of distributed applications and provides a runtime environment for them. This role can also provide specialized containers that wrap a certain class of legacy applications or systems.
An expert in distributed systems, transactions, and security. A container is a runtime system for one or multiple enterprise beans. It provides the glue between enterprise beans and the EJB server. A container can be both, prefabricated code as well as a tool that generates code specific for a particular enterprise bean. A container also provides tools for the deployment of an enterprise bean and hooks into the application for monitoring and management.
The system administrator is concerned with a deployed application. The administrator monitors the running application and takes appropriate action in the case of abnormal behavior of the application. The administrator ensures that the hardware and network hosting the application is maintained and serviceable for the duration of the application's availibility. Typically, an administrator uses enterprise management tools that are connected to the application by the deployer through the hooks provided by the container.
A session bean is an object that executes on behalf of a single client. The container creates the session bean instance in response to a remote task request from a client. A session bean has one client; in a sense, a session bean represents its client in the EJB server. Session beans can also be transaction-aware--they can update shared data in an underlying database but they do not directly represent the shared database data. The life of a session bean is transient and relatively short-lived. Typically, the session bean lives for as long as its client maintains the session "conversation." When the client terminates, the session bean is no longer associated to that client. A session bean is considered transient because the session bean instance is removed should the container crash, and the client must reestablish a new session object to continue.
There are two types of session beans: Stateful Session Beans (SFSB) and Stateless Session Beans (SLSB). Both of these beans must implement javax.ejb.SessionBean
. However their life cycles are different within a EJB container.
A session bean typically maintains the state of the interaction or conversation with its client--that is, the session bean holds information about the client across method invocations and for the duration of the client session. A session bean that maintains its state is called a stateful session bean. When the client ends its interaction with the session bean, the session ends and the bean no longer maintains the state values.
A session bean's life cycle begins when a client invokes a create()
method defined in the bean's home interface. In response to this method invocation, the container does the following:
setSessionContext()
method. This method passes the session bean instance a reference to a session context interface that can be used by the instance to obtain container services and get information about the caller of a client-invoked method.
ejbCreate()
method corresponding to the create()
method called by the EJB client.
After a session bean instance is created, it moves to the ready state of its lifecycle. In this state, EJB clients can invoke the bean's business methods defined in the remote interface. The actions of the container in this state are determined by whether a method is invoked transactionally or non-transactionally:
When a client invokes a transactional business method, the session bean instance is associated with a transaction. After a bean instance is associated with a transaction, it remains associated until that transaction completes. Furthermore, an error results if an EJB client attempts to invoke another method on the same bean instance and invoking that method causes the container to associate the bean instance with another transaction or with no transaction. The container then invokes the following methods:
afterBegin()
method if the session bean implements the SessionSynchronization
interface.
beforeCompletion()
method, if the session bean implements the SessionSynchronization
interface.
The transaction service then attempts to commit the transaction, resulting either in a commit or a roll back. When the transaction completes, the container invokes the bean's afterCompletion()
method (if the bean implements the SessionSynchronization
interface), passing the completion status of the transaction (either commit or rollback) to the afterCompletion()
method.
If a rollback occurs, a stateful session bean can roll back its conversational state to the values contained in the bean instance prior to beginning the transaction. Stateless session beans do not maintain a conversational state, so they do not need to be concerned about rollbacks.
When a client invokes a nontransactional business method, the container simply invokes the corresponding method in the bean class.
The container has a sophisticated algorithm for managing which enterprise bean instances are retained in memory. When a container determines that a stateful session bean instance is no longer required in memory, it invokes the bean instance's ejbPassivate()
method and moves the bean instance into a reserve pool. A stateful session bean instance cannot be passivated (deactivated) when it is associated with a transaction.
If a client invokes a method on a passivated instance of a stateful session bean, the container activates the instance by restoring the instance's state and then invoking the bean instance's ejbActivate()
method. When this method returns, the bean instance is again in the ready state.
Because every stateless session bean instance of a particular type is the same as every other instance of that type, stateless session bean instances are not passivated or activated. These instances exist in a ready state at all times until their removal.
The lifecycle of a stateful session bean ends when an enterprise bean client or the container calls a remove()
method defined in the bean's home interface or remote interface. In response to this method invocation, the container calls the bean instance's ejbRemove()
method. The container can end stateless session beans by this method, or it can pool them for later use.
A container can implicitly call a remove method on an instance after the lifetime of the EJB object has expired. The lifetime of a session EJB object is set in the deployment descriptor with the timeout attribute.
A session bean may also be a stateless session bean. A stateless session bean does not maintain information or state for its client. A client may invoke a method of a stateless session bean to accomplish some objective, but the bean will hold values in its instance variables only for the duration of the method call. The stateless session bean does not retain these values (or state) when the method completes. Thus, all instances of stateless session beans are identical except when they are in the midst of a method invocation. As a result, stateless session beans can support multiple clients. The container can maintain a pool of stateless bean instances, and it can assign any instance to any client.
The stateless session bean's life cycle has two states:
When a bean instance is in the does-not-exist state, this means that it has not yet been instantiated. When a bean instance is instantiated by the container and is ready to serve client requests, it is in the method-ready pool state. The container moves a stateless session bean from the does-not-exist state to the method-ready pool state by performing the following three operations:
Class.newInstance()
method on the stateless bean class.
SessionBean.setSessionContext(SessionContext context)
method on the bean instance.
ejbCreate()
method is invoked on the bean instance.
An entity bean represents an object view of persistent data maintained in a domain model, as well as methods that act on that data. To be more specific, an entity bean maps to a record in your domain model. In a relational database context, one bean exists for each row in a table. A primary key identifies each entity bean. Entity beans are created by using an object factory create()
method. Access to entity beans may be shared by more than one client--multiple clients can simultaneously access an entity bean. Entities access and update the underlying data within the context of a transaction so that data integrity is maintained. Entity beans are also implicitly persistent as an EJB object can manage its own persistence or delegate its persistence to its container. Based on the type of persistence in entity beans are divided into two types:
Container Managed Persistence (CMP) allows developers to build EJB components without having to directly deal with persistence during development. For CMP Entity Beans, the EJB container is responsible for persisting the state of the entity beans and synchronization of instance fields within the persistence store (the database). This means that the container would, for example, manage both generating and executing SQL code to read and write to the database. Because it is container-managed, the implementation is independent of the data source. All container-managed fields need to be specified in the deployment descriptor for the persistence to be automatically handled by the container. CMP Entity Beans are wrappers for persistent data--commonly in the form of relational database tables--with additional support for transaction control and security.
For BMP Entity Beans, the entity bean is directly responsible for persisting its own state and the container does not need to generate any database calls. Each BMP EJB is responsible for storing and retrieving its own state from a backing store in response to specific "hook" messages (like ejbLoad()
and ejbStore()
) that are sent to it at appropriate times during its lifecycle. Consequently, this implementation is less adaptable than the previous one as the persistence needs to be hard-coded into the bean.
An entity bean is considered to be long-lived and its state is persistent. It lives as long as the data remains in the database, rather than for the life of the application or server process. An entity bean survives the crash of the EJB container. Once an enterprise bean is deployed into a container, clients can create and use instances of that bean as required. Within the container, instances of an enterprise bean go through a defined life cycle. The events in an enterprise bean's life cycle are derived from actions initiated by either the client or the container. The life cycle of entity beans has three states:
At this stage, no instances of the bean exist. An entity bean instance's life cycle begins when the container creates that instance. After creating a new entity bean instance, the container invokes the instance's setEntityContext()
method. This method passes to the bean instance a reference to an entity context interface that can be used by the instance to obtain container services and to retrieve information about the caller of the client-invoked method.
Once an entity bean instance is created, it is placed in a pool of available instances of the specified entity bean class. While the instance is in this pool, it is not associated with a specific EJBObject
. Every instance of the same enterprise bean class in this pool is identical. While an instance is in this pooled state, the container can use it to invoke any of the bean's finder methods.
When a client needs to work with a specific entity bean instance, the container picks an instance from the pool and associates it with the EJBObject
initialized by the client. An entity bean instance is moved from the pooled to the ready state if there are no available instances in the ready state.
There are two events that cause an entity bean instance to be moved from the pooled state to the ready state:
create()
method in the bean's home interface to create a new and unique entity of the entity bean class (and a new record in the data source). As a result of this method invocation, the container calls the bean instance's ejbCreate()
and ejbPostCreate()
methods. The new EJBObject
is associated with the bean instance.
ejbActivate()
method to associate the bean instance with the existing EJBObject
.
When an enterprise bean instance is in the ready state, the container can invoke the instance's ejbLoad()
and ejbStore()
methods to synchronize the data in the instance with the corresponding data in the data source. In addition, the client can invoke the bean instance's business methods when the instance is in this state. All interactions required to handle an entity bean instance's business methods in the appropriate transactional (or non-transactional) manner are handled by the container, unless the EJB developer wrote the bean to handle these interactions itself. When a container determines that an entity bean instance in the ready state is no longer required, it moves the instance to the pooled state. This transition to the pooled state results from either of the following events:
ejbPassivate()
method.
remove()
method on the EJBObject
associated with the bean instance or on the EJB home object. When the remove()
method is called, the underlying entity is removed permanently from the data source.
The state that an entity bean represents is shared and transactional. In contrast, if a session bean has state, it must be private and conversational.
The problem of persistence is complex, and many research projects are being carried out on this subject. One of the important points to remember is that at runtime, objects (as it happens, EJBs) are not isolated entities but referenced mutually. Therefore, the problem of persistence does not concern isolated objects, but complex object graphs. There are many questions to answer. How can an object graph in memory be projected on a disk and vice versa? How can synchronization problems between the graph on disk and the graph in memory be resolved? How do you go about loading in memory only the parts of the graph being used at a given moment? How can the graph be saved in a relational database (object-relational mapping technologies)?
The EJB specification attempts to render container-managed persistence with a clean separation between an entity bean and its persistent representation. That is, a separation between the data logic methods (such as the logic in an entity bean to add two fields together) and JDBC. The reason this separation is valuable is that the persistent representation of an entity bean (such as changing from a relational database to an object database) can be modified without affecting the entity bean logic.
To achieve this clean separation, container-managed persistent entity bean classes must be written to be devoid of any JDBC or other persistence logic. The container then generates the JDBC by subclassing your entity bean class. The generated subclass inherits from your entity bean class. Thus, all container-managed persistent entity beans are each broken up into two classes: the superclass (which the user writes, and contains the entity bean data logic) and the subclass (which the container generates, and contains the persistence logic). With these two classes, a clean separation of entity bean logic and persistent representation is achieved. The actual entity bean is a combination of the superclass and the subclass.
A transaction is a set of statements that must be processed as a single unit. Transactions must have four properties recalled with the acronym ACID: Atomicity, Consistency, Isolation and Durability.
The EJB specification describes the creation of applications that enforce transactional consistency on the data manipulated by the enterprise beans. However, unlike other specifications that support distributed transactions, the EJB specification does not require enterprise bean and EJB client developers to write any special code to use transactions. Instead, the container manages transactions based on two deployment descriptor attributes associated with the EJB module and the enterprise bean. EJB application developers are freed to deal with the business logic of their applications.
A J2EE 1.3 compliant EJB container should support flat transactions, the most common kind of transctions. A flat transaction cannot have any child (nested) transactions. These are the only transaction types supported by EJBs.
The JTA APIs specifies start and end transactions.
interface javax.transaction.UserTransaction { public abstract void begin(); public abstract void commit(); public abstract void rollback(); public abstract void setRollbackOnly(); public abstract int getStatus(); public abstract void setTransactionTimeout(int); } interface javax.transaction.Status { public static final int STATUS_ACTIVE; public static final int STATUS_MARKED_ROLLBACK; public static final int STATUS_PREPARED; public static final int STATUS_COMMITTED; public static final int STATUS_ROLLEDBACK; public static final int STATUS_UNKNOWN; public static final int STATUS_NO_TRANSACTION; public static final int STATUS_PREPARING; public static final int STATUS_COMMITTING; public static final int STATUS_ROLLING_BACK; }
The JTA UserTransaction
interface is actually an interface to the application server's transaction manager. It is the public API exposed by the transaction manager. To get a reference to this, you must look up the interface via JNDI, just like you use JNDI to lookup EJB homes, JDBC drivers, etc. The application server must publish the JTA under "java:comp/UserTransaction
".
Context ctx = new InitialContext(...); javax.transaction.UserTransaction userTran = (javax.transaction.UserTransaction) PortableRemoteObject.narrow( ctx.lookup("javax.transaction.UserTransaction"), javax.transaction.UserTransaction.class);
Transaction boundaries mark the beginning and end of transactions. The application developer chooses the boundaries. The J2EE specification mentions three ways of controlling transactional boundaries: programmatically inside bean code (bean-managed transactions), programmatically from client code (client-managed transactions), and declaratively inside deployment descriptors (container-managed transactions).
A Java client can use the javax.transaction.UserTransaction
interface to explicitly demarcate transaction boundaries. The client program obtains the javax.transaction.UserTransaction
interface using the JNDI API.The EJB specification does not imply that the javax.transaction.UserTransaction
is available to all Java clients. The J2EE specification specifies the client environments in which the javax.transaction.UserTransaction
interface is available.
Whenever a client invokes an enterprise bean, the container interposes on the method invocation. The interposition allows the container to control transaction demarcation declaratively through the transaction attributes set in the deployment descriptor.
For example, if an enterprise bean method is configured with the "Required" transaction attribute, the container behaves as follows: if the client request is not associated with a transaction context, the container automatically initiates a transaction whenever a client invokes an enterprise bean method that requires a transaction context. If the client request contains a transaction context, the container includes the enterprise bean method in the client transaction.
An entity bean must always be designed with container-managed transaction demarcation. For entity beans using container-managed persistence, transaction isolation is managed by the data access classes that are generated by the container provider's tools. The tools must ensure that the management of the isolation levels performed by the data access classes will not result in conflicting isolation level requests for a resource manager within a transaction.
The enterprise bean with bean-managed transaction demarcation must be a session bean. An instance that starts a transaction must complete the transaction before it starts another new transaction. A session bean can use the EJBContext
and the javax.transaction.UserTransaction
object to programmatically demarcate transactions. For session beans with bean-managed transaction demarcation, the bean code can specify the desirable isolation level programmatically in the enterprise bean's methods using the resource manager specific API. For example, the bean provider can use the java.sql.Connection.setTransactionIsolation(...)
method to set the appropriate isolation level for database access.
For transactions, a session bean can either use container-managed transactions or bean-managed transactions. Entity beans must use container-managed transactions. Whether an enterprise bean uses bean-managed or container-managed transaction demarcation, the burden of implementing transaction management is on the EJB container and server provider.
The transaction isolation attribute tells the container how to limit concurrent reads in a database. The EJB 1.1 specification removed the guidelines for managing transaction isolation levels for beans with container-managed transaction demarcation. But since bean deployers still require mechanisms to govern EJB concurrency, WebSphere continues to support it along with other mechanisms discussed in the next section.
Using CMP, different databases need different SQL statements while trying to acquire a read/write lock at the "database" level as opposed to optimistic/pessimistic concurrency or locking at the container/bean level. For example, MS-SQL Server needs a "SELECT ... AT ISLOLATION SERIALIZABLE", Oracle needs a "SELECT ... FOR UPDATE" as a method of acquiring 'locks' or in other words at a transaction isolation level 'Serializable' to prevent dirty/unrepeatable/phantom reads. Hence, it is difficult to use generic SQL clauses in conjunction with transactions and locks at the database level without resorting to vendor-specific clauses.
The need is for a simple time stamp/versioning mechanism in EJB 1.1 (even EJB 2.0 seems to imply that acquiring a read/write lock at the database level is up to the EJB vendor, which vendors may or may not provide). All that the time stamp and versioning do is compare versions when the client sends data over for modification. The reading could have been done by different clients in different transactions. Hence, if another client tries to update the same data in the entity bean instance, the version numbers will not match if the data has been updated by another client, and an exception can be raised that effectively tells the client to 'refresh' the information, i.e. get the data again to see what might have changed since the client first requested it for modification. This is analogous to performing an "Update <table> set <fields> where <fields = fields_read_at_transaction_start>". The only difference is that the above technique works across transactions, i.e. it prevents a client from overwriting committed changes made by another client.
Session beans that use bean-managed transaction have transaction attributes associated with each method of the bean. The attribute value tells the container how it must manage the transactions that involve this bean. There are six different transaction attributes that can be associated with each method of a bean. This association is done at deployment time by the application assembler or deployer.
EJB supports distributed flat transactions. The distribution mechanism makes it possible to involve bean objects on multiple EJB servers or to update data in multiple databases in a single transaction. Every client method invocation on a bean is supervised by the bean's container, which makes it possible to manage the transactions according to the transaction attributes that are specified in the corresponding bean's deployment descriptor.
A particular transaction attribute can be associated with an entire bean and apply to all its methods or just to an individual method. The scope of a transaction is defined by the transaction context that is shared by the participating bean objects.
EJB containers allow smart caching of entity beans, which allow some operations to occur in memory rather than at database level. Caching conserves system resources used in making a database connection by eliminating database accesses to unchanged data. There are three caching options available for the container in committing a transaction:
Option A : The container caches a readily available instance between transactions, which has explicit access to the state of the object in the persistent storage. That is, each instance of the EJB will be held in memory. This option is supported by WebSphere and OC4J but should only be used in a single node system. Neither WebSphere nor OC4J enforce this restriction, hence, it is the bean deployer's responsibility to ensure that this restriction is satisfied. This means that the beans using this option will only be used within a single container. It is thus the responsibility of all clients of that bean to always direct their requests to the one bean instance within that specific container.
Option B: The container caches the instance between transactions which does not have access to the persistent object state. This option is not supported by WebSphere nor OC4J.
Option C: The container does not cache the instance between transactions. An entity bean's state is read once per transaction at the beginning of each transaction- even if the value did not change from the last time it was read. The instance is returned to the pool after the transaction is completed. This is the default option supported by WebSphere and OC4J and should be used in multiple node configurations.
WebSphere supports EJB 1.0 specification with some additional features. WebSphere supports:
javax.transaction.UserTransaction
WebSphere Advanced Edition 3.5.3 does not support these EJB 1.1 features:
javax.security.Principal
interface
WebSphere and VisualAge for Java extend the EJB specification with the following features:
The EJB specification does not provide a standard mechanism to let the container check if the bean's state has changed within a unit of work. The specification assumes that all beans accessed during a transaction are "dirty," and must have their state written back to the persistent store at the end of a transaction. WebSphere provides an extension to the EJB specification with the const method flag in the deployment descriptor of entity beans. It lets the developer tell the container which methods are const or read-only--in other words, it doesn't change the state of the bean. For these methods EJB container does not call ejbLoad
at the end of the method call.
WebSphere uses a concept called a "FinderHelper" to define the finder logic for CMP entity beans.The following finder logic is required for each finder method (other than the findByPrimaryKey
method) contained in the home interface of an entity bean with CMP:
<Name>
BeanFinderHelper
, where <Name>
is the name of the enterprise bean (for example, AccountBeanFinderHelper
).
String
constant named <findMethodName>
QueryString
, where <findMethodName>
is the name of the finder method. The String
constant can contain zero or more question marks (?) that are replaced from left to right with the value of the finder method's arguments when that method is invoked.
Public interface AccountBeanFinderHelper {
String findLargeAccountsQueryString ="select * from
ejb.accountbeantblwhere balance > ?"; }
This file contains one static java.lang.String
field for each finder method declared in the EJB home interface. The strings are initialized with SQL queries executed dynamically when bean instances are retrieved in a finder method. Note that this file is specific to the WebSphere application server.
The CMP model in WebSphere allows a set of entity EJBs to be read from a relational database in the find
XXX()
method with only single SQL SELECT call. This is much more efficient then BMP case, which requires N+1 SQL calls to accomplish the same task.
WebSphere supports two-phase commits for distributed transactions for Oracle , DB2, and Sybase and MQ Series. Distributed transaction support is also provided for Oracle and Microsoft SQL Server using the Merant drivers in addition to the existing support for DB2 and Sybase. WebSphere 3.5.3 also supports distributed transactions over EJBs and JMS.
WebSphere never passivates an active bean, i.e. a bean participating in a transaction. WebSphere will throw a ROLLBACK exception back to the client.
WebSphere also makes the UserTransaction
interface available to Java clients including servlets, JSPs, and standalone programs.
WebSphere provides EJB inheritance similar to Java class inheritance.This EJB inheritance model is specific to the IBM EJB development environment. This is an extension of the EJB specification. In EJB inheritance, an enterprise bean inherits properties, such as CMP fields and association roles, methods, and method-level control descriptor attributes from another enterprise bean that resides in the same EJB group.
Support for chaining distributed exceptions is provided by the com.ibm.websphere.exception
Java package. The following classes and interfaces make up this package
DistributedException
DistributedExceptionEnabled
DistributedExceptionInfo
ExceptionInstantiationException
An access bean adapts an enterprise bean to the JavaBeans programming model by hiding the home and remote interfaces from the access bean user (that is, an EJB client developer). This is specific to IBM WebSphere environment. These access beans are packaged in com.ibm.ivj.ejb.access
. There are three types of access beans:
This facilitates either a session or entity bean to be used like a standard Java bean. It hides the enterprise bean home and remote interfaces from you. Each Java bean wrapper that you create extends the com.ibm.ivj.ejb.access.AccessBean
class.
A copy helper is similar to Java bean wrapper, but it also incorporates a single copy helper object that contains a local copy of attributes from a remote entity bean. A user program can retrieve the entity bean attributes from the local copy helper object that resides in the access bean, which eliminates the need to access the attributes from the remote entity bean.
A rowset access bean has all of characteristics of both the Java bean wrapper and copy helper access beans. However, instead of a single copy helper object, it contains multiple copy helper objects. Each copy helper object corresponds to a single enterprise bean instance.
WebSphere supports one-to-one and one-to-many associations for CMP beans. The generated code is specific to WebSphere and VisualAge for Java environment specific.
In the EJB 1.1 specification, the application would have been required to throw an EJBException
, but this has not yet been implemented in WebSphere Advanced Edition 3.5.3.
There are four aspects of an EJB that differ between WebSphere and OC4J:
.ser
file in WebSphere 3.5.
The following features cannot be migrated to OC4J:
In general, enterprise beans written to version 1.0 of the EJB specification are mostly compatible with version 1.1. However, you need to modify or recompile enterprise bean code in the following cases:
Changes specific to transaction API:
Any EJB application code still using the following IBM specific transaction support packages for user transactions need to be migrated. This involves finding the import statements in the EJB source files containing
import com.ibm.db2.jdbc.app.jta.javax.transaction.*
and changing it to:
import javax.transaction.*
javax.jts.UserTransaction
interface.
The package name of the javax.jts interface
has changed to javax.transaction
, and there have been minor changes to the exceptions thrown by the methods of this interface. An enterprise bean that uses the javax.jts.UserTransaction
interface needs to be modified to use the new name javax.transaction.UserTransaction
.
UserTransaction
object lookup
The UserTransaction
object is obtained differently for enterprise beans written to version 1.1 of the EJB specification. Under WebSphere version 1.0, it was obtained as:
initialContext.lookup("jta/UserTransaction")
This should be changed to the following in OC4J:
initialContext.lookup("java:comp/UserTransaction")
getCallerIdentity()
or isCallerInRole(Identity identity)
or getEnvironment()
methods of the javax.ejb.EJBContext
interface.
These methods of EJBContext
class were deprecated in EJB 1.1 because the class java.security.Identity
is deprecated in the Java 2 platform. While OC4J still provides backward compatibility for implementation of these methods, Oracle recommends moving to standard methods.
The return value of ejbCreate()
is different in EJB 1.1 than in EJB 1.0. A CMP bean written to the EJB 1.0 specification needs to be recompiled to work with OC4J. The ejbCreate()
method has different return values for BMP and CMP entity beans in EJB 1.0 specification. BMP entity beans return the unique identity of the bean, which is the primary key. The CMP Entity Bean returns void
.
The following code shows the different method signatures used for container-managed and bean-managed ejbCreate()
methods in an EJB 1.0. CMP entity bean:
public class EmployeeCMP implements javax.ejb.EntityBean { public int Empid; public void ejbCreate(int empID) { Empid= empID; } // more bean code follows .... }
The code below shows a BMP entity bean, EJB 1.0:
public class EmployeeBMP implements javax.ejb.EntityBean { public int Empid; public EmployeePK ejbCreate(int myID) { Empid= empID; // do a database insert using JDBC EmployeePK pk = new AccountPK(empID); return pk; } // more bean code follows ... }
The EJB 1.1 specification changes this so that both bean-managed and container-managed entities have to return the primary key type from the ejbCreate()
methods. However, container-managed beans are required to return null
instead of a primary key object.
The OC4J server puts finder queries in XML deployment descriptors using proprietary query language formats, as compared to the WebSphere finder helper classes. When deploying CMP entity beans you can ignore finder helper classes and replace them by manually editing queries into the OC4J deployment descriptor orion-ejb-jar.xml
. For example, the following finder helper in WebSphere EJB can be migrated to OC4J as follows:
In WebSphere:
public interface AccountBeanFinderHelper { String findLargeAccountsQueryString ="select * from ejb.accountbeantbl where balance > ?"; }
To migrate this functionality to OC4J, change the generated orion-ejb-jar.xml
by modifying the <finder-method/>
tag section with:
public static final String findByOwner_query="full: select "+ "*"+"from from ejb.accountbeantbl"+ "where balance >$1";
Note that this query uses "full:
" at the beginning to specify that this is the full text of the query.
As pointed out earlier, WebSphere provides an option in its Administration Console to indicate to the EJB container that a particular method is read-only. OC4J uses a runtime approach to provide the same feature. In order to migrate EJBs containing read-only methods you must:
public boolean isModified()
" in the bean code.
boolean
flag that is set each time the bean is modified. This flag should be cleared in ejbStore()
.
If isModified()
returns false
, OC4J knows that it does not need to talk to the database.
The following code changes are necessary:
javax.jts.UserTransaction
interface) to bound related method invocations into a single atomic unit of work. The EJB specification does not, however, define how a client application can create a transaction; it does not specify how to obtain a reference to the javax.jts.UserTransaction
interface in a client application. In the absence of this specification, the application server provides a class that may be used to access the JTS CosTransactions . This is the current interface, which is a superset of the javax.jts.UserTransaction
interface. This interface allows transactions to be created, suspended and resumed, and committed or aborted. To obtain a reference to the org.omg.CosTransactions.Current
interface, the client application may simply call the static getCurrent()
method in the com.ibm.ejs.client.EJClient
class. For example:
org.omg.CosTransactions.Current current =com.ibm.ejs.client.EJClient.getCurrent(); current.begin(); // do transactional work current.commit(false);
OC4J does not support client-managed transactions. Any client-managed transactions can be deployed as container managed transactions by changing the transaction properties in the EJB deployment descriptors.
InitialContext
object. This object will be hooked to the naming service running in the application server based on two parameters: host name and port of the naming service (PROVIDER_URL
) and the name of the initial context factory (INITIAL_CONTEXT_FACTORY
). This information is provided to the constructor of the InitialContext
as a java.util.Properties
object. When migrating from WebSphere to OC4J, these values must be changed. For example:
In WebSphere, the initial naming context is obtained by the following code:
java.util.Properties properties =new java.util.Properties(); properties.put(javax.naming.Context.PROVIDER_URL,"iiop:///"); properties.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.ibm.ejs.ns.jndi.CNInitialContextFactory"); javax.naming.InitialContext initialContext = new javax.naming.InitialContext(properties); initialContext.lookup("com/ibm/Hello");
The string "///
" for the PROVIDER_URL
property indicates to the runtime environment to find the naming service at the standard port on the local machine. The general form of the PROVIDER_URL
string is "iiop://
hostname
:
port
/
". The value of the second property, INITIAL_CONTEXT_FACTORY
, is the class name of the naming service factory.
To migrate to OC4J, this code must be changed as follows:
javax.naming.InitialContext initialContext = new javax.naming.InitialContext();
Object yourEJBHome = initialContext.lookup("java:comp/env/ejb/Hello")
If the client and EJBs are deployed on different OC4J instances:
java.util.Properties properties = new java.util.Properties(); properties.put(javax.naming.Context.PROVIDER_URL, "ormi://<hostname>:<port>/<application>"); properties.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.evermind.server.rmi.initialContextFactory"); properties.put(javax.naming.Context.SECURITY_PRINCIPAL,"admin"); properties.put(javax.naming.Context.SECURITY_CRIDENTIALSL,"123"); javax.naming.InitialContext initialContext = new javax.naming.InitialContext(properties); Object yourEJBHome = initialContext.lookup("Java:comp/env/ejb/Hello")
The SECURITY_PRINCIPAL
and SECURITY_CREDENTIAL
properties are the administrator username and password specified during installation of OC4J.
The following should be noted:
TRANSACTION_SERIALISABLE
has different semantics in OC4J and WebSphere. In WebSphere, if two transactions both read the same row (entity), they acquire a read lock on that row.
loadForUpdate
method. This method will acquire a lock on the bean's state in the underlying data store.
With EJBs, O-R mapping is done differently according to the EJB container used (in practice, according to the application server).This means that in order to import an EJB into a different container, it is necessary to go through this development phase again. This is the case with WebSphere and OC4J, since they have different ways of generating O-R mapping classes. WebSphere uses the WebSphere Studio and the VisualAge for Java development environment to generate code for O-R mapping. WebSphere supports one-to-one and one-to-many associations among EJBs.
OC4J supports the EJB 2.0 O-R mapping model. EJB 2.0 is not backward compatible with EJB 1.1, rather, it is a complete break with the old way of doing CMP persistence. OC4J supports one-to-one and one-to-many associations.
Since WebSphere 3.5.x is at the EJB 1.0 specification level, the EJB JAR files are deployed using serialized deployment descriptors. These cannot be directly deployed on OC4J, which supports the EJB 2.0 XML-based deployment descriptors. Consequently, the EJB JAR files must be re-archived using the EJB 2.0 deployment descriptors. Package individual or multiple EJB components in EJB JAR files and place assembly and deployment properties for EJBs in the standard deployment descriptor XML file (ejb-jar.xml
) within the EJB archive file. The deployment descriptor contains attribute and environment settings that define how the container invokes enterprise bean functionality. Every enterprise bean (both session and entity) must have a deployment descriptor that contains settings for the following attributes:
RunAsMode
and RunAsIdentity
attributes - the RunAsMode
attribute defines the identity used to invoke the method. If a specific identity is required, the RunAsIdentity
attribute is used to specify that identity. The RunAsMode
attribute is used by the WebSphere EJB servers; the RunAsIdentity
attribute is not.
The deployment descriptor for an entity bean must also contain settings for the following attributes. These attributes can be set on the bean only. They cannot be set on a per-method level.
STATEFUL
or STATELESS
.
These attributes can be set for the entire enterprise bean or for the individual methods in the bean. The container uses the definition of the bean-level attribute unless a method-level attribute is defined, in which case the latter is used.
<container-transaction> <method> <ejb-name>LogEntEJB</ejb-name> <method-name>*</method-name> <trans-attribute>Required</trans-attribute> </method> <method> <ejb-name>EntUtenteEJB</ejb-name> <method-name>*</method-name> <trans-attribute>Required</trans-attribute> </method> </container-transaction>
To cache EJB instances, you specify maximum instance limits for each entity bean in orion-ejb-jar.xml
with your application and place it in the META_INF
directory.
<?xml version="1.0"?> <orion-ejb-jar> <enterprise-beans> <entity-deployment name="BeanName" location="BeanName" max-instances="5" validity-timeout="3600000"/> </enterprise-beans> </orion-ejb-jar>
|
![]() Copyright © 2003 Oracle Corporation. All Rights Reserved. | | Ad Choices. |
|