Skip Headers

Oracle Application Server Containers for J2EE Services Guide
10g (9.0.4)

Part Number B10326-01
Go To Documentation Library
Home
Go To Table Of Contents
Contents
Go To Index
Index

Go to previous page Go to next page

7
Java Transaction API

This chapter describes the Oracle Application Server Containers for J2EE (OC4J) Java Transaction API (JTA). This chapter covers the following topics:

Introduction

Applications deployed in the application server can demarcate transactions using Java Transaction API (JTA) 10.1.

For example, Enterprise Java Beans (EJBs) with bean-managed transactions, servlets, or Java objects that are deployed in the OC4J container can begin and end (demarcate) a transaction.

This chapter discusses the method for using JTA in OC4J. It does not cover JTA concepts--you must understand how to use and program global transactions before reading this chapter. See the Sun Microsystems Web site for more information.

Code examples are available for download from the OTN OC4J sample code site:

http://otn.oracle.com/sample_code/tech/java/oc4j/htdocs/oc4jsamplecode/oc4j-demo-ejb.html

JTA involves demarcating transactions and enlisting resources.

Demarcating Transactions

Your application demarcates transactions. Enterprise Java Beans use JTA 1.0.1 for managing transactions through either bean-managed or container-managed transactions.

Enlisting Resources

The complexity of your transaction is determined by how many resources your application enlists with the transaction.

Single-Phase Commit

Single-phase commit (1pc) is a transaction that involves only a single resource. JTA transactions consist of enlisting resources and demarcating transactions.

Enlisting a Single Resource

To enlist the single resource in the single-phase commit, perform the following two steps:

Configure the Data Source

Use an emulated data source for a single phase commit. Refer to Chapter 4, "Data Sources", for information on emulated and nonemulated data source types.

Use the default data source (data-sources.xml) that comes with a standard OC4J installation if you can for the single-phase commit JTA transaction. After modifying this data source url attribute with your database URL information, retrieve the data source in your code using a JNDI lookup with the JNDI name configured in the ejb-location attribute. Configure a data source for each database involved in the transaction.

<data-source
  class="com.evermind.sql.DriverManagerDataSource"
  name="OracleDS"
  location="jdbc/OracleCoreDS"
  xa-location="jdbc/xa/OracleXADS"
  ejb-location="jdbc/OracleDS"
  connection-driver="oracle.jdbc.driver.OracleDriver"
  username="scott"
  password="tiger"
  url="jdbc:oracle:thin:@myhost:myport:mySID"
  inactivity-timeout="30"
/>

In the preceding code, myhost, myport, and mySID are entries that you must change. The values that actually appear likely are not valid for your installation.

For information about the expected attribute definitions, see Chapter 4, "Data Sources".

Retrieve the Data Source Connection

Before executing any SQL statements against tables in the database, you must retrieve a connection to that database. For these updates to be included in the JTA transaction, perform the following two steps:

Perform JNDI Lookup

After the transaction has begun, look up the data source from the JNDI name space. Here are the two methods for retrieving the data source:

Perform JNDI Lookup on Data Source Definition

You can perform a lookup on the JNDI name bound to the data source definition in the data-sources.xml file and retrieve a connection, as follows:

Context ic = new InitialContext();
DataSource ds = (DataSource) ic.lookup("jdbc/OracleDS");
Connection conn = ds.getConnection();
Perform JNDI Lookup Using Environment

You can perform a lookup on a logical name that is defined in the environment of the bean container. For more information, see Chapter 4, "Data Sources". Basically, define the logical name in the J2EE deployment descriptor in ejb-jar.xml or web.xml as follows:

<resource-ref>
     <res-ref-name>jdbc/OracleMappedDS</res-ref-name>
     <res-type>javax.sql.DataSource</res-type>
     <res-auth>Container</res-auth>
</resource-ref>

Map the <res-ref-name> in the OC4J-specific deployment descriptor (for example, orion-ejb-jar.xml) to the JNDI name that is bound in the data-sources.xml file as follows, where "jdbc/OracleDS" is the JNDI name defined in the data-sources.xml file:

<resource-ref-mapping name="jdbc/OracleMappedDS" location="jdbc/OracleDS" />

Then retrieve the data source using the environment JNDI lookup and create a connection, as shown in the following:

InitialContext ic = new InitialContext();
DataSource ds = ic.lookup("java:comp/env/jdbc/OracleMappedDS");
Connection conn = ds.getConnection();

If you are using JDBC, you can start preparing and executing statements against the database. If you are using SQLJ, create a default context to specify in the #sql statement.

Retrieve a Connection

Retrieve a connection off this data source object using the getConnection method. You can do this in one of two ways:

Use the method with no arguments when the data source definition contains the user name and password that you want.

Use the other method when the data source definition does not contain a user name and password or when you want to use a user name and password that is different from what is specified in the data source.

Example 7-1 shows a small portion of an employee session bean that uses container-managed transactions (CMTs) and uses SQLJ for updating the database.

Example 7-1 Retrieving a Connection Using Portable JNDI Lookup

int empno = 0;
double salary = 0.0;
DataSource remoteDS;
Context ic;

//Retrieve the initial context. No JNDI properties are necessary here
ic = new InitialContext ();

//Look up the DataSource using the <resource-ref> definition
remoteDS = (DataSource)ic.lookup ("java:comp/env/jdbc/OracleMappedDS");

//Retrieve a connection to the database represented by this DataSource
Connection remoteConn = remoteDS.getConnection ("SCOTT", "TIGER");
// Use remoteDS.getConnection () if the data source definition contains
// the user name and password that you want

//Since this implementation uses SQLJ, create a default context for this 
//connection.
DefaultContext dc = new DefaultContext (remoteConn);

//Perform the SQL statement against the database, specifying the default 
//context for the database in brackets after the #sql statement.
#sql [dc] { select empno, sal  from emp where ename = :name  };

Demarcating the Transaction

With JTA, you can demarcate the transaction yourself by specifying that the bean is bean-managed transactional, or designate that the container should demarcate the transaction by specifying that the bean is container-managed transactional. Container-managed transaction is available to all EJBs. However, the bean-managed transactions are available for session beans and MDBs.


Note:

The client cannot demarcate the transaction. Propagation of the transaction context cannot cross OC4J instances. Thus, neither a remote client nor a remote EJB can initiate or join the transaction.


Specify the type of demarcation in the bean deployment descriptor. Example 7-2 shows a session bean that is declared as container-managed transactional by defining the <transaction-type> element as Container. To configure the bean to use bean-managed transactional demarcation, define this element to be Bean.

Example 7-2 Session Bean Declared as Container-Managed Transactional

</session>
  <description>no description</description>
  <ejb-name>myEmployee</ejb-name>
  <home>cmtxn.ejb.EmployeeHome</home>
  <remote>cmtxn.ejb.Employee</remote>
  <ejb-class>cmtxn.ejb.EmployeeBean</ejb-class>
  <session-type>Stateful</session-type>
  <transaction-type>Container</transaction-type>
  <resource-ref>
   <res-ref-name>jdbc/OracleMappedDS</res-ref-name>
   <res-type>javax.sql.DataSource</res-type>
   <res-auth>Application</res-auth>
  </resource-ref>
</session>

Container-Managed Transactional Demarcation

If you define your bean to use CMTs, then you must specify how the container manages the JTA transaction for this bean in the <trans-attribute> element in the deployment descriptor (shown in Example 7-1). Table 7-1 briefly describes the transaction attribute types that you should specify in the deployment descriptor.

Table 7-1 Transaction Attributes  
Transaction Attribute Description

NotSupported

The bean is not involved in a transaction. If the bean invoker calls the bean while involved in a transaction, then the invoker's transaction is suspended, the bean executes, and when the bean returns, the invoker's transaction is resumed.

Required

The bean must be involved in a transaction. If the invoker is involved in a transaction, the bean uses the invoker's transaction. If the invoker is not involved in a transaction, the container starts a new transaction for the bean. This attribute is the default.

Supports

Whatever transactional state that the invoker is involved in is used for the bean. If the invoker has begun a transaction, the invoker's transaction context is used by the bean. If the invoker is not involved in a transaction, neither is the bean.

RequiresNew

Whether or not the invoker is involved in a transaction, this bean starts a new transaction that exists only for itself. If the invoker calls while involved in a transaction, then the invoker's transaction is suspended until the bean completes.

Mandatory

The invoker must be involved in a transaction before invoking this bean. The bean uses the invoker's transaction context.

Never

The bean is not involved in a transaction. Furthermore, the invoker cannot be involved in a transaction when calling the bean. If the invoker is involved in a transaction, then a RemoteException is thrown.


Note:

The default transaction attribute (<trans-attribute> element) for each type of entity bean is as follows:

  • For CMP 2.0 entity beans, the default is Required.

  • For MDBs, the default is NotSupported.

  • For all other entity beans, the default is Supports.


Example 7-3 shows the <container-transaction> portion of the deployment descriptor; it demonstrates how this bean specifies the RequiresNew transaction attribute for all (*) methods of the myEmployee EJB.

Example 7-3 <container-transaction> in Deployment Descriptor

   <assembly-descriptor>
      <container-transaction>
         <description>no description</description>
         <method>
            <ejb-name>myEmployee</ejb-name>
            <method-name>*</method-name>
         </method>
        <trans-attribute>RequiresNew</trans-attribute>
      </container-transaction>
   </assembly-descriptor>

No bean implementation is necessary to start, commit, or roll back the transaction. The container handles all of these functions based on the transaction attribute that is specified in the deployment descriptor.

Bean-Managed Transactions

If you declare the bean as bean-managed transactional (BMT) within the <transaction-type>, then the bean implementation must demarcate the start, commit, or rollback for the global transaction. In addition, you must be careful to retrieve the data source connection after you start the transaction and not before.

Programmatic Transaction Demarcation

For programmatic transaction demarcation, the bean developer can use either the JTA user transaction interface or the JDBC connection interface methods. The bean developer must explicitly start and commit or roll back transactions within the timeout interval.

Web components (JSP, servlets) can use programmatic transaction demarcation. Stateless and stateful session beans can use it; entity beans cannot, and thus must use declarative transaction demarcation.

Client-side Transaction Demarcation

This form of transaction demarcation is not required by the J2EE specification, and is not recommended for performance and latency reasons. OC4J does not support client-side transaction demarcation.

JTA Transactions

The Web component or bean writer must explicitly issue begin, commit, and rollback methods of the UserTransaction interface as follows:

Context initCtx = new Initial Context(); 
ut = (UserTransaction)  initCtx.lookup("java:comp/UserTransaction"); 
... 
ut.begin(); 
// Commit the transaction started in ejbCreate. 
Try { 
        ut.commit(); 
} catch (Exception ex) { .....} 

JDBC Transactions

The java.sql.Connection class provides commit and rollback methods. JDBC transactions implicitly begin with the first SQL statement that follows the most recent commit, rollback, or connect statement.

The following code example assumes that there are no errors. You can download this example from the OC4J sample code OTN site:

http://otn.oracle.com/sample_code/tech/java/oc4j/htdocs/oc4jsamplecode/oc4j-demo-ejb.html

This example demonstrates the combination of demarcating a transaction and enlisting the database resources in the following manner:

  1. It retrieves the UserTransaction object from the bean context.

  2. It starts the transaction with the begin method.

  3. It enlists the database.

This example is the same as in Example 7-1, but it is surrounded by UserTransaction begin() and commit() methods.

DataSource remoteDS;
Context ic;
int empno = 0;
double salary = 0.0;
//Retrieve the UserTransaction object. Its methods are used for txn demarcation
UserTransaction ut = ctx.getUserTransaction ();

//Start the transaction
ut.begin();

//Retrieve the initial context. No JNDI properties are necessary here
ic = new InitialContext ();

//Lookup the OrionCMTDataSource that was specified in the data-sources.xml 
remoteDS = (DataSource)ic.lookup ("java:comp/env/jdbc/OracleCMTDS");

//Retrieve a connection to the database represented by this DataSource
Connection remoteConn = remoteDS.getConnection ("SCOTT", "TIGER");

//Since this implementation uses SQLJ, create a default context for this 
//connection.
DefaultContext dc = new DefaultContext (remoteConn);

//Perform the SQL statement against the database, specifying the default 
//context for the database in brackets after the #sql statement.
#sql [dc] { select empno, sal  from emp where ename = :name  };

//Assuming everything went well, commit the transaction.
ut.commit();

Two-Phase Commit

The main focus of JTA is to declaratively or programmatically start and end simple and global transactions. When a global transaction is completed, all changes are either committed or rolled back. The difficulty in implementing a two-phase commit transaction is in the configuration details. For two-phase commit, you must use only a nonemulated data source. For more information on nonemulated data sources, refer to "Non-emulated Data Sources".

Figure 7-1 contains an example of a two-phase commit engine--jdbc/OracleCommitDS--coordinating two databases in the global transaction--jdbc/OracleDS1 and jdbc/OracleDS2. Refer to this example when going through the steps for configuring your JTA two-phase commit environment.

Configuring Two-Phase Commit Engine

When a global transaction involves multiple databases, the changes to these resources must all be committed or rolled back at the same time. That is, when the transaction ends, the transaction manager contacts a coordinator--also known as a two-phase commit engine--to either commit or roll back all changes to all included databases. The two-phase commit engine is an Oracle9i Database Server database that you must configure with the following:

To facilitate this coordination, perform the following database and OC4J configuration steps shown in the next two subsections.

Database Configuration Steps

Designate and configure an Oracle9i Database Server database as the two-phase commit engine with the following steps:

  1. Create the user (for example, COORDUSR) on the two-phase commit engine that facilitates the transaction and perform the following three actions:

    1. The user opens a session from the two-phase commit engine to each of the involved databases.

    2. Grant the user the CONNECT, RESOURCE, CREATE SESSION privileges to be able to connect to each of these databases. The FORCE ANY TRANSACTION privilege allows the user to commit or roll back the transaction.

    3. Create this user and grant these permissions on all databases involved in the transaction.

    For example, if the user that is needed for completing the transaction is COORDUSR, do the following on the two-phase commit engine and each database involved in the transaction:

    CONNECT SYSTEM/MANAGER;
    CREATE USER COORDUSR IDENTIFIED BY COORDUSR;
    GRANT CONNECT, RESOURCE, CREATE SESSION TO COORDUSR;
    GRANT FORCE ANY TRANSACTION TO COORDUSR;
    
    
  2. Configure fully-qualified public database links (using the CREATE PUBLIC DATABASE LINK command) from the two-phase commit engine to each database that can be involved in the global transaction. This is necessary for the two-phase commit engine to communicate with each database at the end of the transaction. The COORDUSR must be able to connect to all participating databases using these links.

    Figure 7-1 shows two databases involved in the transaction. The database link from the two-phase commit engine to each database is provided on each OrionCMTDataSource definition in a <property> element in the data-sources.xml file. See the next step for the "dblink" <property> element.

    Figure 7-1 Two-Phase Commit Diagram

    Text description of o_1000.gif follows.

    Text description of the illustration o_1000.gif

OC4J Configuration Steps

  1. To configure two-phase commit coordination, when you have defined the database that is to act as the two-phase commit engine, configure it as follows:

    1. Define a nonemulated data source, using OrionCMTDataSource, for the two-phase commit engine database in the data-sources.xml file. The following code defines the two-phase commit engine OrionCMTDataSource in the data-sources.xml file.

      <data-source
        class="com.evermind.sql.OrionCMTDataSource"
        name="OracleCommitDS"
        location="jdbc/OracleCommitDS"
        connection-driver="oracle.jdbc.driver.OracleDriver"
        username="coordusr"
        password="coordpwd"
        url="jdbc:oracle:thin:@machine0:port0:SID0"
        inactivity-timeout="30"
      />
      
      
    2. Refer to the two-phase commit engine data source in either the global application.xml file or local orion-application.xml file. The global XML file exists in the config directory. The local XML file exists in the application EAR file.

      Configure the two-phase commit engine in the orion-application.xml file as follows:

      <commit-coordinator>
       <commit-class class="com.evermind.server.OracleTwoPhaseCommitDriver" />
       <property name="datasource" value="jdbc/OracleCommitDS" />
       <property name="username" value="coordusr" />
       <property name="password" value="coordpwd" />
      </commit-coordinator>
      


      Note:

      The password attribute of the <commit-coordinator> element supports password indirection. For more information, refer to the Oracle Application Server Containers for J2EE Security Guide.


      The parameters are as follows:

      The two-phase commit coordinator can be specified at the application level by defining the <commit-coordinator> element in the application.xml file.

      • The OracleTwoPhaseCommitDriver class is defined in the <commit-class> element.

      • The JNDI name for the OrionCMTDataSource is identified in the <property> element whose name is "datasource".

      • The user name is identified in the <property> element "username".

      • The password is identified in the <property> element "password".

  2. To configure databases that will participate in a global transaction, configure nonemulated data source objects of type OrionCMTDataSource for each database involved in the transaction with the following information:

    1. The JNDI bound name for the object.

    2. The URL for creating a connection to the database.

    3. The fully-qualified database link from the two-phase commit engine to this database (for example, LINK1.machine1.COM). This is provided in a <property> element within the data source definition in the data-sources.xml file.

    The following OrionCMTDataSource objects specify the two databases involved in the global transaction. Notice that each of them has a <property> element named "dblink" that denotes the database link from the two-phase commit engine to itself.

    <data-source
      class="com.evermind.sql.OrionCMTDataSource"
      name="OracleCMTDS1"
      location="jdbc/OracleDS1"
      connection-driver="oracle.jdbc.driver.OracleDriver"
      username="scott"
      password="tiger"
      url="jdbc:oracle:thin:@machine1:port1:SID1""
      inactivity-timeout="30">
      <property name="dblink"
       value="LINK1.machine1.COM"/>
    </data-source>
    
    <data-source
      class="com.evermind.sql.OrionCMTDataSource"
      name="OracleCMTDS2"
      location="jdbc/OracleDS2"
      connection-driver="oracle.jdbc.driver.OracleDriver"
      username="scott"
      password="tiger"
      url="jdbc:oracle:thin:@machine2:port2:SID2""
      inactivity-timeout="30">
      <property name="dblink"
       value="LINK2.machine2.COM"/>
    </data-source>
    
    


    Note:

    If you change the two-phase commit engine, you must update all database links--both within the new two-phase commit engine as well as within the OrionCMTDataSource <property> definitions.


After the two-phase commit engine and all the databases involved in the transaction are configured, you can start and stop a transaction in the same manner as the single-phase commit. See "Single-Phase Commit" for more information.

Limitations of Two-Phase Commit Engine

The following data-sources.xml configuration is supported for two-phase commit in the Oracle Application Server Containers for J2EE (OC4J) release:

<data-source
       class="com.evermind.sql.OrionCMTDataSource"
       location="jdbc/OracleDS"
       connection-driver="oracle.jdbc.driver.OracleDriver"
       username="scott"
       password="tiger"
       url="jdbc:oracle:thin:@hostname:port number:SID"
/>

Two-phase commit works only with a nonemulated data source configuration, as shown in the preceding. The URLs of all participating nonemulated data sources must point to an Oracle database instance. Only multiple Oracle resources participating in a global transaction will have ACID (atomicity, consistency, isolation, durability) semantics after the commit. In summary, two-phase commit is supported only with Oracle database resources, but full recovery is always supported.

In the emulated configuration, two-phase commit may seem to work, but is not supported, as there is no recovery. The ACID properties of the transaction will not be guaranteed and may cause problems for an application.

Configuring Timeouts

You can configure timeouts in the server.xml file in the <transaction-config> element, which has a timeout attribute. This attribute specifies the maximum amount of time (in milliseconds) that a transaction can take to finish before it is rolled back due to a timeout. The default value is 30000. This timeout is a default timeout for all transactions that are started in OC4J. You can change the value by using the dynamic API UserTransaction.setTransactionTimeout(milliseconds).

The server DTD defines the <transaction-config> element as follows:

<!ELEMENT transaction-config (#PCDATA)>
<!ATTLIST transaction-config timeout CDATA #IMPLIED>

Recovery for CMP Beans When Database Instance Fails

You should be aware of any failure of the back-end database--especially if the CMP bean is acting within a transaction. If the database instance fails, then you may have to retry the operations that you were trying to accomplish during the moment of failure. The following sections detail how to implement recovery whether the CMP bean is within a container-managed transaction or a bean-managed transaction:

Connection Recovery for CMP Beans That Use Container-Managed Transactions

If you define your CMP bean with container-managed transactions, you can set a retry count and interval for re-establishing the transaction. Then, if the database instance fails and your connection goes down while interacting within a transaction, the EJB container automatically retrieves a new connection to the database (within the specified interval) until the count is reached and re-executes the operations within the TRY block where the failure occurred.

To set the automatic retry count and interval, set the following optional attributes in the <entity-deployment> element in the CMP bean orion-ejb-jar.xml file:

Connection Recovery for CMP Beans That Use Bean-Managed Transactions

The EJB container does not manage bean-managed transactional CMP beans or EJB clients. Thus, when they receive and exception denoting that the JDBC connection has failed, each must understand if this is a scenario where the method within the transaction can be retried.

To determine if this is a retry scenario, provide the database connection and the SQL exception as parameters in the DbUtil.oracleFatalError() method, which determines if you can get a new connection and retry your operations. If this method returns true, then you should create a new connection to continue the transaction.

The following code demonstrates how to execute the DbUtil.oracleFatalError method.

if ((DbUtil.oracleFatalError(sql_ex, db_conn)) 
{ 
 //retrieve the database connection again.
 //re-execute operations in the try block where the failure occurred. 
} 

Using Transactions With MDBs

Transactions, both BMT and CMT are supported within MDBs. The default transaction attribute (trans-attribute) for MDBs is NOT_SUPPORTED.

In accordance with the specification, MDBs support only REQUIRED and NOT_SUPPORTED. If you specify another attribute, such as SUPPORTS, then the default of NOT_SUPPORTED is used. An error is not thrown in this situation.

You can define a transaction timeout, as defined in the transaction-timeout attribute, in the <message-driven-deployment> element of the ejb-jar.xml file. This attribute controls the transaction timeout interval (in seconds) for any container-managed transactional MDB. The default is one day or 86,400 seconds. If the transaction has not completed in this time frame, the transaction is rolled back.

Transaction Behavior for MDBs using OC4J JMS

If you have heterogeneous or multiple resources involved in a single transaction, then two-phase commit is not supported. For example, if a MDB communicates to a CMP bean, which uses the database for persistence, and receives messages from a client through OC4J JMS, then this MDB includes two resources, the database and OC4J JMS. In this case, two-phase commit it not supported.

If you have no two-phase commit support, then there is no guarantee that when a transaction commits, that all systems committed correctly. The same is true for rollbacks. You are not guaranteed ACID-quality global transactions without a two-phase commit engine.

Transaction Behavior for MDBs using Oracle JMS

Oracle JMS uses a back-end Oracle database as the queue and topic facilitator. Since Oracle JMS uses database tables for the queues and topics, you may need to grant two-phase commit database privileges for your user.

OC4J optimizes one-phase commit for you, so that it is not necessary to use two-phase commit unless you have two databases (or more than one data source) involved in the transaction. If you do use two-phase commit, it is fully supported within Oracle JMS.

You should be aware of any failure of the back-end database--especially if the MDB bean is acting within a transaction. If the database instance fails, then you may have to retry the operations that you were trying to accomplish during the moment of failure. The following sections detail how to implement recovery whether the MDB bean is within a container-managed transaction or a bean-managed transaction:

MDBs that Use Container-Managed Transactions

If you define your MDB with container-managed transactions, you can set a retry count and interval for re-establishing the JMS session. Then, if your transaction fails while interacting with a database, the container automatically retries (within the specified interval) until the count is reached. To set the automatic retry count and interval, set the following optional attributes in the <message-driven-deployment> element in the MDB orion-ejb-jar.xml file:

MDBs that Use Bean-Managed Transactions and JMS Clients

The container does not manage bean-managed transactional MDBs or JMS clients. Thus, when they receive an exception denoting that the JDBC connection has failed, each must understand if this is a scenario where the method within the transaction can be retried. To determine if this is a retry scenario, input the database connection and the SQL exception as parameters in the DbUtil.oracleFatalError() method.

You must retrieve the database connection from the JMS session object and the SQL exception from the returned JMS exception, as follows:

  1. Retrieve the underlying SQL exception from the JMS exception.

  2. Retrieve the underlying database connection from the JMS session.

  3. Execute the DbUtil.oracleFatalError() method to find out if the exception indicates an error that you can retry. If this method returns true, then you should create a new JMS connection, session, and possible sender to continue the JMS activity.

The following code demonstrates how to process the JMS exception, jmsexc, to pull out the SQL exception, sql_ex. Also, the database connection, db_conn, is retrieved from the JMS session, session. The SQL exception and database connection are input parameters for the DbUtil.oracleFatalError method.

try 
{ 
 .. 
} 
catch(Exception e ) 
{ 
 if (exc instanceof JMSException) 
 { 
  JMSException  jmsexc = (JMSException) exc; 
  sql_ex = (SQLException)(jmsexc.getLinkedException()); 
  db_conn = (oracle.jms.AQjmsSession)session.getDBConnection(); 

  if ((DbUtil.oracleFatalError(sql_ex, db_conn)) 
  { 
    // Since the DBUtil function returned true, regain the JMS objects
    // 1a. Look up the Queue Connection Factory
    QueueConnectionFactory qcf = (QueueConnectionFactory)
               ctx.lookup ("java:comp/resource/" + resProvider + 
               "/QueueConnectionFactories/myQCF"); 
    // 1b. Lookup the Queue  
    Queue queue = (Queue) ctx.lookup ("java:comp/resource/" + resProvider +
                                       "/Queues/rpTestQueue");
      
    //2 & 3. Retrieve a connection and a session on top of the connection
    //2a. Create queue connection using the connection factory.
    QueueConnection qconn = qcf.createQueueConnection();
    //2a. We're receiving msgs, so start the connection.
    qconn.start();

    // 3. create a session over the queue connection.
    QueueSession qsess = qconn.createQueueSession(false,
                                                   Session.AUTO_ACKNOWLEDGE);

     //4. Since this is for a queue, create a sender on top of the session. 
    //This is used to send out the message over the queue.
    QueueSender snd = sess.createSender (q);
 
  } 
 } 
} 


Go to previous page Go to next page
Oracle
Copyright © 1996, 2003 Oracle Corporation.

All Rights Reserved.
Go To Documentation Library
Home
Go To Index
Index