|
Articles Index
By Beth Stearns
(April 2001)
This article describes the J2EE Connector architecture Common Client
Interface (CCI) API. The CCI provides the access from J2EE clients, such as
enterprise beans, JavaServer Pages (JSP) technology, and servlets, to an underlying enterprise
information system (EIS). The J2EE Connector architecture, and the CCI API,
are currently available as a beta release.
The CCI simplifies
the problem of writing code to connect a client to an underlying EIS's data
store. This problem exists for both application developers and for EIS
vendors. The EIS vendor can use the CCI to write a generic interface to its
database product. With this one interface, their product will work with
clients on any compliant J2EE platform. Likewise, application developers
only need to learn and use one set of API calls to connect their client to
any underlying EIS, rather than having to learn a different API for each
EIS. In addition, even if an enterprise changes its underlying EIS, its
application code will not have to be changed to maintain this connectivity.
Introduction to the CCI
To access an EIS from a J2EE client, you need to first establish and define
a connection to the EIS. The term EIS refers to a data store or database, or
other mechanism that stores data on an enterprise scale. (For simplicity,
this article uses the term database to refer to any kind of data store.) For
each operation you want to perform on the data store or database, you
establish and define an interaction. You also create a record for
transferring data into or out of the database. Rather than directly access
the EIS, clients use the CCI to interact with a resource adapter, which is a
software component provided by an EIS vendor for a specific EIS.
By designing resource adapters that comply with the specifications of the Connector architecture,
EIS vendors make it possible for developers to write transportable code for
accessing EISs without having to know the underlying semantics of the resource manager that
handles the EIS.
CCI Elements
These are the Java classes defined in the CCI and some of the more important methods
for performing database operations.
ConnectionFactoryEstablishes a connection instance with EIS
getConnection creates a Connection instance (managed by either a container or a
component)
getRecordFactory creates a RecordFactory instance
ConnectionRepresents a connection (using the resource adapter) to an EIS
createInteraction creates an Interaction object so that database operations can be
performed
getLocalTransaction creates a LocalTransaction object
close closes a connection to EIS
ConnectionSpecDefines user name, password, and other properties in a connection
request; serves as properties parameter
InteractionCreates an interaction with the connected EIS
executeinvokes procedures stored in an EIS for performing database operations
InteractionSpecDefines an interaction with the connected EIS, including schema,
catalog, and stored function names
RecordFactoryCreates Record object
createIndexedRecord creates an ordered collection of Record instances
createMappedRecord creates a collection of Record instances ordered by key-value
pairs
createResultSet creates a collection of Record instances as a result set of tabular
data
RecordSuperclass for Record instances
add adds data to input record
LocalTransactionEstablishes a context for a local transaction
begin starts a database transaction
commit completes an atomic database transaction
rollback cancels transaction, returning database to initial state
There is a prescribed manner that a client or application component must follow to use the
CCI to interact with an underlying EIS. The component must establish a connection to the
EIS's resource manager using the ConnectionFactory. The Connection object represents the
actual connection to the EIS and is used for subsequent interactions with the EIS. The
ConnectionSpec object defines the connection request information, that is, the user name,
password, and any other needed properties.
The component performs its interactions with the EIS, such as accessing data from a specific
table, using an Interaction object. The InteractionSpec object defines the Interaction object,
specifying the database schema and catalog and any predefined database operations stored in
the database. When the application component reads data from the EIS (such as from
database tables) or writes to those tables, it uses a Record instance, (a MappedRecord,
IndexedRecord, or ResultSet instance) instantiated by the RecordFactory object.
An application component uses the LocalTransaction object only when it manages its own
transaction and persistence. For example, an enterprise bean can choose to use
bean-managed persistence (BMP), in which case it manages its own transactions. However, if the bean
uses container-managed persistence (CMP), then the bean lets the container completely
handle the transaction and it has no need to use the LocalTransaction object. The LocalTransaction
object enables the data access to be conducted as an all-or-nothing transaction.
Steps in Using a Connector
The basic programming steps in using the CCI API and a connector to access a database or
data store are:
- Establish a JNDI context for your session. User name and password are required to
access the EIS.
- Use the JNDI
lookup method to locate the ConnectionFactory for the resource adapter.
- Use the
ConnectionFactory method getConnection to open the connection.
- Use the Connection method
createInteraction to create a new Interaction instance.
All operations on the underlying EIS are done through an Interaction object.
- Instantiate an object representing the
InteractionSpec interface.
- Use the
ConnectionFactory method getRecordFactory to get a reference to the RecordFactory.
- Create
Record instances as necessary using the appropriate RecordFactory create
method, such as createIndexedRecord. Be sure to establish whether the record is for
input, output, or both input and output (inout).
- If you are managing your own transaction and persistence, begin a transaction so that
you can recover if a problem occurs.
- Perform the desired operation on the data store. The example in this article uses database stored
procedures to operate on the database. Note that the elements in the
Record instances
need to map to the appropriate parameters in the stored procedures.
- If you manage your own transaction, commit the transaction or rollback if there
are errors.
- Close the connection to the EIS.
Overview of the Example of a Session Bean Using a Resource Adapter
This example shows how a session bean uses a resource adapter to add and read records in a
relational database. The example shows how to invoke stored procedures, which are business
logic functions stored in a database and specific to an enterprise's operation. Stored procedures
consist of SQL code to perform operations related to the business needs of an organization.
They are kept in the database and can be invoked when needed, just as you might
invoke a Java method. In addition to showing how to use the CCI to invoke stored procedures,
the Example also illustrates how to pass parameters to stored procedures and how to map the
parameter data types from SQL to Java.
You should have already installed the resource adapter for the EIS and its connection factory.
Refer to the J2EE reference implementation documentation
for instructions on how to do this.
The example session beanAcctManage is like any other session bean. It has a home
interface (AcctManageHome.java), a remote interface
(AcctManage.java), and an implementation class
(AcctManageEJB.java). The client is
AcctManageClient.java.
The AcctManage home interface is like any other session bean home interface it extends
EJBHome and defines a create method to return a reference to its remote interface. The
AcctManage remote interface defines the bean's two methods that may be called by a client:
public void insertAcct(String acctName, int amt)
throws RemoteException;
public int getAcctAmt() throws RemoteException;
Using Database Stored Procedures
Before going further, it is important to understand database stored procedures. This example
shows you how to invoke a database stored procedure; it is the stored procedure that actually
reads or writes to the database.
A stored procedure is a business logic method or function that is stored in a database and is
specific for the enterprise's business. Typically, stored procedures are written in SQL code,
though in certain cases (such as with Cloudscape) they may actually be written in Java code.
Stored procedures perform operations related to the business needs of an organization. They
are kept in the database and applications can invoke them when needed.
Stored procedures are typically SQL statements. This example calls two stored procedures:
GETAMT and ADDACCT. The GETAMT procedure merely gets the account amounts from
records in the Account table, as follows:
SELECT AMT(*) FROM ACCOUNT
The ADDACCT procedure adds an account record to the table. The record has two values,
which are passed to the procedure as parameters:
INSERT INTO ACCOUNT VALUES (?,?)
Defining Input and Output Parameters
When you invoke a stored procedure from your application component, you may have to pass
argument values to the procedure. For example, when you invoke the ADDACCT procedure,
you pass it two values for the Account record elements. Likewise, you must be prepared to
receive values that a stored procedure returns.
- The stored procedure, in turn, passes its set of parameters to the database manager (DBMS)
to carry out its operation and may receive values back from the DBMS.
- Database stored procedures specify, for each of their parameters, the SQL type of the parameter value and the
mode of the parameter.
- Mode can be input (
IN), output (OUT), or both input and output
(INOUT).
- An input parameter only passes data in to the DBMS while an output parameter
only receives data back from the DBMS.
- An
INOUT parameter accepts both input and output
data.
When you use the CCI execute method to invoke a database stored procedure, you also
create an instance of an InputRecord if you're passing a parameter to the stored procedure and,
if the stored procedure you're executing returns data, possibly an OutputRecord instance.
The InputRecord and OutputRecord are instances of the supported Record types: IndexedRecord,
MappedRecord, or ResultSet. In this example, it instantiates an InputRecord and
an OutputRecord that are both IndexedRecord instances.
The InputRecord maps the IN and INOUT parameters for the stored procedure, while the
OutputRecord maps the OUT and INOUT parameters. Each element of an input or output
record corresponds to a stored procedure parameter. That is, there is an entry in the
InputRecord for each IN and INOUT parameter declared in the stored procedure. Not only does
the InputRecord have the same number of elements as the procedure's input parameters, they
are declared in the same order as in the procedure's parameter list. The same holds true for
the OutputRecord, though its list of elements matches only the OUT and INOUT
parameters.
For example, suppose you have a stored procedure X that declares three parameters. The first
parameter is an IN parameter, the second is an OUT parameter, and the third is an INOUT
parameter. Figure 1 shows how the elements of an InputRecord and an OutputRecord map to
this stored procedure.
Figure 1: Mapping Stored Procedure Parameters to CCI Record Elements
You must declare the parameter type and mode before calling a stored procedure with
parameters. Keep in mind, though, that you may have to declare the parameter mode differently
depending on the underlying DBMS. Oracle designates the parameter's mode in the
stored procedure declaration, along with the parameter's type declaration. For example, an
Oracle ADDACCT procedure declares its two IN parameters as follows:
procedure ADDACCT (
acctname IN VARCHAR2, amt IN INTEGER)
An Oracle GETAMT procedure declares its parameter amt as an OUT parameter:
procedure GETAMT (amt OUT INTEGER)
Cloudscape, which declares stored procedures using a standard Java method signature,
indicates an IN parameter using a single value and an INOUT parameter as an array. The
method's return value is the OUT parameter. For example, Cloudscape declares the IN
parameters (acctName and amt) for ADDACCT and the OUT
parameter (the method's return
value) for GETAMT follows:
public static void ADDACCT(String acctname, int amt)
public int GETAMT()
If amt was an INOUT parameter, then Cloudscape declares it as:
public static void ADDACCT(String acctname,
int[] amt)
Oracle declares an INOUT parameter as:
procedure ADDACCT (acctname IN VARCHAR2,
amt INOUT INTEGER)
Mapping Java Types to SQL Types
Remember to map the SQL type of each value to its corresponding Java type. Thus, if the
SQL type is integer, then the InputRecord or OutputRecord element must be defined as a
Integer object. If the SQL type is a VARCHAR, then the Java type must be a String object.
When you add the element to the Record, you declare it to be an object of the proper type.
For example, add an integer and a string element to an InputRecord as follows:
iRec.add (new Integer (intval));
iRec.add (new String ("Customer Account"));
The JDBC specification defines the complete SQL to Java type mapping.
Programming with the CCI
To illustrate how to use the CCI API, take a look at a session bean and a client of that bean.
These pieces of code illustrate how clients invoke the different CCI methods that resource
adapters built on CCI might make available. (This example uses the sample resource adapters
supplied with the J2EE reference implementation.)
Now examine the session bean implementation class to see how it uses the CCI. To
begin with, notice that AcctManageEJB imports the javax.resource CCI interfaces and
classes, along with javax.resource.ResourceException:
import javax.resource.cci.*;
import javax.resource.ResourceException;
Getting the Connection
Prior to obtaining a database connection, the AcctManageEJB session bean does some set up
work in its setSessionContext method. Specifically, the setSessionContext
method sets the
user and password values, and instantiates a ConnectionFactory. These values and objects
remain available to the other session bean methods.
public void setSessionContext(SessionContext sc) {
try {
this.sc = sc;
// Establish a JNDI initial context.
Context ic = new InitialContext();
// Use the JNDI InitialContext.lookup
//method to find the user
// and password values.
user = (String) ic.lookup("java:comp/env/user");
password =
(String) ic.lookup("java:comp/env/password");
// Use the lookup method to locate the
// ConnectionFactory for the CCI
// resource adapter and obtain a reference to it.
cf = (ConnectionFactory)
ic.lookup("java:comp/env/CCIEIS");
...
|
AcctManageEJB uses its private method getCCIConnection to establish a
connection to the underlying resource manager or database. An AcctManage client cannot
invoke this method directly. Rather, the session bean uses this method internally to establish
a connection to the database. The getCCIConnection method invokes the getConnection
method to obtain the connection. Prior to this call, it instantiates a CciConnectionSpec
object, which represents the implementation of the ConnectionSpec interface, with the user
and password values. It uses this CciConnectionSpec object to pass the user and password
values to the connection.
private Connection getCCIConnection() {
Connection con = null;
try {
// Instantiate a new CciConnectionSpec
// object with the user and
// password values obtained by the
// setSessionContext method. The
// CciConnectionSpec class is the
// implementation of the
// ConnectionSpec interface.
ConnectionSpec spec =
new CciConnectionSpec(user, password);
// Call the ConnectionFactory's getConnection
// method to obtain a connection
to the database.
// Use the CciConnectionSpec object to
// pass the required properties to
// the ConnectionFactory. The getConnection
// method returns a Connection object.
con = cf.getConnection(spec);
} catch (ResourceException ex) {
...
}
return con;
}
|
The AcctManageEJB bean also includes a private method, closeCCIConnection, to close a
connection. The method invokes the Connection object's close method from within a try/catch block. Like the getCCIConnection method, this is a private method intended to be
called from within the session bean.
private void closeCCIConnection(
Connection con) {
try {
con.close();
} catch (ResourceException ex) {
ex.printStackTrace();
}
}
|
Reading Database Records
The AcctManageEJB's getAcctAmt method illustrates how to use the CCI to read records
from a database table. This method does not directly read the database records itself; instead,
it invokes a procedure stored in the database called GETAMT.
It is the stored procedure that
actually reads the records in the database table.
The CCI provides interfaces for three types of records: IndexedRecord, MappedRecord, and
ResultSet. These three record types inherit from the base interface, Record. They differ only
in how they map the record elements within the record. The example uses IndexedRecord.
IndexedRecord holds its record elements in an ordered, indexed collection based on
java.util.List. As a result, a Iterator is used to access the individual elements in the list.
Begin by looking at how the getAcctAmt method uses the CCI to invoke a database
stored procedure. The method first obtains a connection, then creates a new Interaction
instance by calling the Connection object's createInteraction method. The Interaction
object enables a bean to execute EIS functions such as invoking stored procedures.
public int getAcctAmt() {
int count = -1;
try {
// Obtain a connection to the database.
Connection con = getCCIConnection();
// Create a new Interaction instance
// so that the session bean can invoke
// the EIS stored procedure.
Interaction ix = con.createInteraction();
...
|
Then, the bean must instantiate a CciInteractionSpec object to pass properties to the
Interaction object. The CciInteractionSpec is the implementation class for the InteractionSpec
interface, and it holds properties required by the Interaction object to interact with an EIS
instance. Such properties include schema name, catalog name, and the stored procedure
name. The session bean uses the CciInteractionSpec methods setSchema,
setCatalog, and
setFunctionName to set the required values into the instance's fields. This example passes
GETAMT to setFunctionName because this is the name of the stored procedure it intends to
invoke.
...
// Instantiate a CciInteractionSpec object.
CciInteractionSpec iSpec =
new CciInteractionSpec();
// Set values for the CciInteractionSpec
instance's
//fields: user name and stored procedure name. Our
//example uses a Cloudscape database,
which does not
// require a catalog name.
iSpec.setSchema(user);
iSpec.setCatalog(null);
iSpec.setFunctionName("GETAMT");
...
|
Now, the getAcctAmt method uses the ConnectionFactory to obtain a reference to a
RecordFactory. With the RecordFactory reference, it invokes the createIndexedRecord method to
create an IndexedRecord instance. (The bean could also use the RecordFactory to create
MappedRecord or ResultSet instances.) It creates the IndexedRecord using the name
InputRecord, which it passes to createIndexedRecord as an argument. This completes the set up
work that must be done prior to invoking the stored procedure.
...
// Obtain a RecordFactory reference.
RecordFactory rf = cf.getRecordFactory();
// Invoke the RecordFactory's
// createIndexedRecord method.
IndexedRecord iRec =
rf.createIndexedRecord("InputRecord");
...
|
The getAcctAmt method uses the Interaction instance's execute method to
invoke the stored
procedure GETAMT. The bean passes two objects to the execute method:
the InteractionSpec
object, whose properties reference the GETAMT stored procedure, and the IndexedRecord
object, which is expected to be an input Record. The execute method returns an output
Record object.
...
// Use the Interaction instance's execute
// method to invoke GETAMT.
oRec =ix.execute(iSpec,iRec);
...
|
Then, the bean uses an Iterator to retrieve the individual elements from the Record returned
by the execute method. It first casts the output Record object to an IndexedRecord.
Note that
IndexedRecord contains an iterator which it inherits from java.util.List. The bean uses the
iterator.hasNext method to retrieve each element in the returned record object. Each
extracted element is an Object, and the bean evaluates whether it is an integer or decimal
value and processes it accordingly. When it has completely processed the record, it closes
the connection to the database and returns the results.
...
// Retrieve the individual elements from
// the returned IndexedRecord using the
// iterator.hasNext method.
Iterator iterator =
((IndexedRecord)oRec).iterator();
while(iterator.hasNext()) {
Object obj = iterator.next();
if (obj instanceof Integer) {
amt = ((Integer)obj).intValue();
}
else if (obj instanceof BigDecimal) {
amt = ((BigDecimal)obj).intValue();
}
}
// Close the connection to the database.
closeCCIConnection(con);
} catch (ResourceException ex) {
...
}
return amt;
}
|
Inserting Database Records
The AcctManageEJB session bean implements the insertAcct method to add new records
into the Account database table. This method invokes the ADDACCT stored procedure, which
inserts an account record and sets values for the two elements in the recordaccount name
and amountusing values passed to it as arguments.
The insertAcct method shown here illustrates how to use the CCI to invoke a stored
procedure that expects to be passed argument values. Much of the set up is the same as what was
done in the getAcctAmt method. The method first establishes a connection to the database,
then creates a new Interaction instance to execute the stored procedure. The bean also
instantiates a CciInteractionSpec object (from the CciInteractionSpec class that implements the
InteractionSpec interface) to hold the properties that the Interaction object requires to
communicate to the database, then it uses the functions setSchema, setCatalog, and
setFunctionName to set the necessary property values. Notice that the method sets the
function name
to ADDACCT.
public void insertAcct(String acctName, int amt) {
try {
// Establish a connection to the database.
Connection con = getCCIConnection();
// Create a new Interaction instance
// to execute the stored procedure.
Interaction ix = con.createInteraction();
// Instantiate a CciInteractionSpec object to
// pass necessary properties to the
// Interaction object.
CciInteractionSpec iSpec =
new CciInteractionSpec();
// Set schema, catalog and function name
// values in the CciInteractionSpec
// object fields.
iSpec.setFunctionName("ADDACCT");
iSpec.setSchema(user);
iSpec.setCatalog(null);
...
|
Next, the bean obtains a reference to a RecordFactory using the ConnectionFactory's
getRecordFactory method. It then invokes the RecordFactory's createIndexedRecord method to
create a new IndexedRecord called InputRecord. At this point, the bean needs to set values
for the two elements in the input record that are to be passed to the ADDACCT stored procedure.
The bean uses the IndexedRecord object's add method to set up these values in the new
record. It calls the add method once for each element. It sets the first record element to the
account name value and the second element to the amount value. (Notice that the int value
amt is set to an Integer object when it is passed to the add method.
The add method accepts
only Java objects.) The AcctManageEJB bean is now ready to pass the new account record to
the stored procedure which will add it to the database.
It calls the Interaction instance's execute method to invoke the stored
procedure ADDACCT.
Just as when invoking the GETAMT procedure, the bean passes two objects to the execute
method: the InteractionSpec object with the correctly set properties for the ADDACCT stored
procedure and the IndexedRecord object representing an input Record. The execute method
is not expected to return anything in this case.
The method completes by closing the connection to the database.
...
// Obtain a reference to a RecordFactory.
RecordFactory rf = cf.getRecordFactory();
// Create a new IndexedRecord called
// InputRecord.
IndexedRecord iRec =
rf.createIndexedRecord("InputRecord");
// Use the IndexedRecord add method to
// add acctName and amt to
// the input record.
boolean flag = iRec.add(name);
flag = iRec.add(new Integer(qty));
// Invoke the Interaction execute method
// to invoke the ADDACCT stored procedure
ix.execute(iSpec,iRec);
// Close the connection to the database.
closeCCIConnection(con);
}catch (ResourceException ex) {
ex.printStackTrace();
}
}
|
Executing a Local Transaction
The previous sections showed how to program with the CCI from an EJB that
uses container-managed persistence. Because the EJB container ensured that the database
access would take place within the context of a transaction, an AcctManage bean using
container-managed persistence did not have to concern itself with these matters. The container
handled starting and ending the transaction, making sure that the database record was
updated without interference from other processes.
However, if your bean uses bean-managed persistence, then it must handle its own transaction.
An enterprise bean with bean-managed persistence uses methods from the LocalTransaction
interface to handle local transactions.
Keep in mind that resource managers typically support two types of transactions: XA
transactions and local transactions. XA transactions refer to the Java mapping of the X/Open XA
protocol. They are often called global transactions, because they can span multiple resource
managers. Typically, XA transactions are managed by an external transaction manager
located on the application server.
Local transactions, on the other hand, are managed by the resource manager itself, and you
can use the CCI API to handle a local transaction. To ensure the integrity of the data, add a
record to the database from within the context of a transaction. To illustrate, look at the modified
the AcctManage bean's insertAcct method that uses the CCI to start and commit, or rollback, a
local transaction.
public void insertAcct(
String acctName, int amt) {
try {
Connection con = getCCIConnection();
Interaction ix = con.createInteraction();
CciInteractionSpec iSpec =
new CciInteractionSpec();
iSpec.setFunctionName("ADDACCT");
iSpec.setSchema(user);
iSpec.setCatalog(null);
RecordFactory rf = cf.getRecordFactory();
IndexedRecord iRec =
rf.createIndexedRecord(
"InputRecord");
boolean flag = iRec.add(acctName);
flag = iRec.add(new Integer(amt));
// Obtain a reference to a transaction
// context
LocalTransaction transaction =
con.getLocalTransaction();
// Start the transaction
transaction.begin();
try {
ix.execute(iSpec, iRec);
// The operation was successful;
// commit the transaction
transaction.commit();
} catch (ResourceException e) {
// An error occurred; rollback
// the transaction
transaction.rollback();
}
closeCCIConnection(con);
}catch(ResourceException ex) {
ex.printStackTrace();
}
}
|
As you can see, most of the code of the insertAcct method is identical to the container-managed
persistence version: Both versions do the following, in the
same order:
- Obtain a connection to the database.
- Create an
Interaction object.
- Create and define properties for an object that implements the
InteractionSpec interface.
- Use the
ConnectionFactory to obtain a reference to the RecordFactory.
- Create an IndexedRecord input Record and sets the values for the two elements in the
Account record: account name and amount.
At this point, the bean-managed persistence version deviates from the container-managed
version. Before invoking the Interaction object's execute method, the bean first obtains a
reference to a transaction. To do this, it invokes the Connection object's
getLocalTransaction
method and instantiates a new LocalTransaction object. The LocalTransaction object
provides the context for the transaction. Then, the bean starts the transaction by invoking the
LocalTransaction object's begin method.
...
// Obtain a reference to a transaction context
LocalTransaction transaction =
con.getLocalTransaction();
// Start the transaction
transaction.begin();
...
|
The bean can now safely do its transactional work. In this case, it invokes the Interaction
object's execute method to execute the stored procedure ADDACCT and insert the new Account
record into the database. The call to execute is the same as in the container-managed
version, except that it is made from within a try block to catch any errors. If the call to execute
is successful, then the bean commits the transaction. Otherwise, it rolls back the transaction
to undo its actions. When a transaction is rolled back, any changes made to the database are
undone and the database is restored to the state it was in prior to the start of the transaction.
...
try {
ix.execute(iSpec, iRec);
transaction.commit();
} catch (ResourceException e) {
transaction.rollback();
}
// Close the connection
...
|
The insertAcct method finishes by closing the connection.
Writing a CCI Client
A client application that relies on a CCI resource adapter is very much like any other J2EE
client application. The AcctManageClient application uses the methods of the
AcctManageEJB session bean to access the Account table in the underlying database.
AcctManageClient invokes the AcctManage getAcctAmt method to read account amounts from the Account
table and the insertAcct method to add records to the table.
Conclusion
By now, you should have a good understanding of how to use the J2EE Connector architecture's Common
Client Interface API. You've seen how to use the different interfaces and classes defined by the
CCI to access a resource adapter for an underlying database or EIS. You've also seen how to use
these methods to invoke procedures stored in the EIS, and to pass parameters to these procedures and
receive values back.
The Connector architecture and the CCI are currently supported by a
significant number of J2EE-compliant EIS vendors and tools vendors. It is
anticipated that most, if not all, J2EE-compliant EIS vendors will support
this technology. As its use becomes more widespread, and particularly as
more and more tools vendors build support of the CCI into their tools, it
will become the standard for J2EE enterprise application connectivity.
About the Author
Beth Stearns is the principal partner of ComputerEase Publishing, a
computer consulting firm she founded in 1982. Her client list includes Sun
Microsystems, Inc., Silicon Graphics, Inc., Oracle Corporation, and Xerox
Corporation. Among her publications are the "Java Native
Interface" chapter in "The Java Tutorial Continued" book in the Addison
Wesley Java series, "The EJB Programming Guide" for Inprise Corporation,
and "Understanding
EDT", a guide to Digital Equipment Corporation's text editor. Most
recently, she is co-author with Vlada Matena of the forthcoming Addison
Wesley Java series book, "Applying Enterprise JavaBeans: Component-Based
Development for the J2EE Platform."
|