4 Programming Tasks

This chapter describes the programming tasks for implementing a WebLogic Server resource adapter. It lists the Java classes that are required by the Java EE Connector Architecture; explains how to program a resource adapter to perform as a startup class; explains how to suspend and resume resource adapter activity; and describes the ExtendedBootstrapContext class.

This chapter includes the following sections:

Required Classes for Resource Adapters

A resource adapter requires the following Java classes, in accordance with Java Connector Architecture:

  • ManagedConnectionFactory

  • ConnectionFactory interface

  • ConnectionFactory implementation

  • Connection interface

  • Connection implementation

These classes are specified in the ra.xml file. For example:

<managedconnectionfactory-class>
com.sun.connector.blackbox.LocalTxManagedConnectionFactory
</managedconnectionfactory-class>

<connectionfactory-interface>
javax.sql.DataSource
</connectionfactory-interface>

<connectionfactory-impl-class>
com.sun.connector.blackbox.JdbcDataSource
</connectionfactory-impl-class>

<connection-interface>
java.sql.Connection
</connection-interface>

<connection-impl-class>
com.sun.connector.blackbox.JdbcConnection
</connection-impl-class>

In addition, if the resource adapter supports inbound messaging, the resource adapter will require an ActivationSpec class for each supported inbound message type. See Message and Transactional Inflow.

The specifics of these resource adapter classes depend on the nature of the resource adapter you are developing.

Generic Work Context

Connector Architecture 1.6 defines the generic work context, a mechanism for a resource adapter to propagate contextual information from an EIS to WebLogic Server during message delivery or when submitting a Work instance. The generic work context comprises a set of classes, interfaces, and methods, and also includes new schema elements supported in WebLogic Server.

The following sections describe these entities added to support the generic work context:

Interfaces, Classes, and Methods Added to Support the Generic Work Context

The following interfaces are added to support the generic work context:

Interface Description
javax.resource.spi.work.WorkContext

Serves as a standard mechanism for a resource adapter to propagate an imported context from an EIS to an application server.

javax.resource.spi.work.WorkContextLifecycleListener

Models the various events that occur during the processing of the WorkContexts associated with a Work instance. This interface may be implemented by a WorkContext instance to receive notifications from the WorkManager when the WorkContext is set as the execution context of the Work instance it is associated with.

javax.resource.spi.work.WorkContextProvider

Specifies the methods a Work instance uses to associate a List of WorkContext instances to be set when the Work instance gets executed by a WorkManager.

The following class is added to support the generic work context:


Class Description
javax.resource.spi.work.WorkContextErrorCodes

Models the possible error conditions that might occur during associating a WorkContext with a Work instance.


The following method is added to BootstrapContext interface to support the generic work context:


Method Description
isContextSupported

A resource adapter can check an application server's support for a particular WorkContext type through this method. This mechanism enables a resource adapter developer to dynamically change the WorkContexts submitted with a Work instance based on the support provided by the application server.


Deployment Descriptor Element Added to Support the Generic Work Context

To support the generic work context, the required-work-context element is added to the ra.xml file schema to represent a WorkContext class that is required by the resource adapter for WebLogic Server to support. For each WorkContext class that is required, an individual required-work-context element is specified.

Note that the @Connector metadata annotation can be used in a resource adapter source file to specify this deployment descriptor information. For more information, see Section 18.4, @Connector, in JSR 322: Java EE Connector Architecture 1.6.

Programming a Resource Adapter to Perform as a Startup Class

The following sections describe programming a resource adapter to perform as a startup class:

Minimum Content of a Resource Adapter

As an alternative to using a WebLogic Server startup class, you can program a resource adapter with a minimal resource adapter class that implements javax.resource.ResourceAdapter, which defines a start() and stop() method.

Note:

Because of the definition of the ResourceAdapter interface, you must also define the endpointActivation(), Deactivation() and getXAResource() methods.

When the resource adapter is deployed, the start() method is invoked. When it is undeployed, the stop() method is invoked. Any work that the resource adapter initiates can be performed in the start() method as with a WebLogic Server startup class.

Example 4-1 shows a resource adapter having a minimum resource adapter class. It is the absolute minimum resource adapter that you can develop (other than removing the println statements). In this example, the only work performed by the start() method is to print a message to stdout (standard out).

Example 4-1 Minimum Resource Adapter

import javax.resource.spi.ResourceAdapter;
import javax.resource.spi.endpoint.MessageEndpointFactory;
import javax.resource.spi.ActivationSpec;
import javax.resource.ResourceException;
import javax.transaction.xa.XAResource;
import javax.resource.NotSupportedException;
import javax.resource.spi.BootstrapContext;
/**
* This resource adapter is the absolute minimal resource adapter that anyone can build (other than removing the println's.)
*/
public class ResourceAdapterImpl implements ResourceAdapter
{
   public void start( BootstrapContext bsCtx )
   {   
      System.out.println( "ResourceAdapterImpl started" );
   }
   public void stop()
   {
      System.out.println( "ResourceAdapterImpl stopped" );
   }
   public void endpointActivation(MessageEndpointFactory messageendpointfactory, ActivationSpec activationspec)
      throws ResourceException
   {
      throw new NotSupportedException();
   }
   public void endpointDeactivation(MessageEndpointFactory messageendpointfactory, ActivationSpec activationspec)
   {
   }
   public XAResource[] getXAResources(ActivationSpec aactivationspec[])
      throws ResourceException
   {
      throw new NotSupportedException();
   }
}

Submitting a Work Instance

Because resource adapters have access to the Work Manager through the BootstrapContext in the start() method, they should submit Work instances instead of using direct thread management. This enables WebLogic Server to manage threads effectively through its self-tuning Work Manager.

Once a Work instance is submitted for execution, the start() method should return promptly so as not to interfere with the full deployment of the resource adapter. Thus, a scheduleWork() or startWork() method should be invoked on the Work Manager rather than the doWork() method.

Example 4-2 shows resource adapter that submits work instances to the Work Manager. The resource adapter starts some work in the start() method, thus serving as a Java EE-compliant startup class.

Example 4-2 Resource Adapter Using the Work Manager and Submitting Work Instances

import javax.resource.NotSupportedException;
import javax.resource.ResourceException;
import javax.resource.spi.ActivationSpec;
import javax.resource.spi.BootstrapContext;
import javax.resource.spi.ResourceAdapter;
import javax.resource.spi.endpoint.MessageEndpointFactory;
import javax.resource.spi.work.Work;
import javax.resource.spi.work.WorkException;
import javax.resource.spi.work.WorkManager;
import javax.transaction.xa.XAResource;
/**
* This Resource Adapter starts some work in the start() method, 
* thus serving as a Java EE compliant "startup class" 
*/
public class ResourceAdapterWorker implements ResourceAdapter
{
   private WorkManager wm;
   private MyWork someWork;
   public void start( BootstrapContext bsCtx )
   {
      System.out.println( "ResourceAdapterWorker started" );
      wm = bsCtx.getWorkManager();
      try
      {
         someWork = new MyWork();
         wm.startWork( someWork );
      }
      catch (WorkException ex)
      {
         System.err.println( "Unable to start work: " + ex );
      }
   }
   public void stop()
   {
   // stop work that was started in the start() method
   someWork.release();
      System.out.println( "ResourceAdapterImpl stopped" );
   }
   public void endpointActivation(MessageEndpointFactory messageendpointfactory,
             ActivationSpec activationspec)
      throws ResourceException
   {
      throw new NotSupportedException();
   }
   public void endpointDeactivation(MessageEndpointFactory
             messageendpointfactory, ActivationSpec activationspec)
   {
   }
   public XAResource[] getXAResources(ActivationSpec activationspec[]) 
      throws ResourceException
   {
      throw new NotSupportedException();
   }
   // Work class
   private class MyWork implements Work
   {
      private boolean isRunning;
      public void run()
      {
         isRunning = true;
         while (isRunning)
         {
         // do a unit of work (e.g. listen on a socket, wait for an inbound msg, 
         // check the status of something)
         System.out.println( "Doing some work" );
         // perhaps wait some amount of time or for some event
         try
         {
            Thread.sleep( 60000 ); // wait a minute
         }
         catch (InterruptedException ex)
         {}
      }
   }
   public void release()
   {
         // signal the run() loop to stop
         isRunning = false;
      }
   }
}

Retrying a Work Submission

There are instances in which the submission of a Work instance by a resource adapter can experience a transient failure. For example, JSR 322: Java EE Connector Architecture 1.6 describes how you can use the optional startTimeout parameter in a WorkManager interface implementation to specify a time interval within which the execution of the Work instance must start. If a Work submission times out, a work submission failure occurs and a WorkRejectedException is generated.

JSR 322: Java EE Connector Architecture 1.6 states that the application server throws out a RetryableWorkRejectedException when it determines that the failure of a Work submission may due to transient causes. When it receives a RetryableWorkRejectedException, the resource adapter may retry submitting the Work instance. WebLogic Server supports the RetryableWorkRejectedException in the following transient failure situations:

  • The Work instance was submitted to a suspended Work Manager.

  • The Work submission has timed out.

Note:

WebLogic Server extends retryable exception support to outbound connection pools if a connection instance attempts to connect to a suspended connection pool. For more information, see Retrying a Connection Attempt.

Suspending and Resuming Resource Adapter Activity

You can program your resource adapter to use the suspend() method, which provides custom behavior for suspending activity. For example, using the suspend() method, you can queue up all incoming messages while allowing in-flight transactions to complete, or you can notify the Enterprise Information System (EIS) that reception of messages is temporarily blocked.

You then invoke the resume() method to signal that the inbound queue be drained and messages be delivered, or notify the EIS that message receipt was re-enabled. Basically, the resume() method allows the resource adapter to continue normal operations.

You initiate the suspend() and resume() methods by making a call on the resource adapter runtime MBeans programmatically, using WebLogic Scripting Tool, or from the WebLogic Server Administration Console. See Start and stop a resource adapter in the Oracle WebLogic Server Administration Console Online Help for more information.

The Suspendable.supportsSuspend() method determines whether a resource adapter supports a particular type of suspension. The Suspendable.isSuspended() method determines whether or not a resource adapter is presently suspended.

A resource adapter that supports suspend(), resume(), or production redeployment must implement the Suspendable interface to inform WebLogic Server that these operations are supported. These operations are invoked by WebLogic Server when the following occurs:

  • Suspend is called by the suspend() method on the connector component MBean.

  • The production redeployment sequence of calls is invoked (when a new version of the application is deployed that contains the resource adapter). See Suspendable Interface and Production Redeployment.

Example 4-3 contains the Suspendable interface for resource adapters:

Example 4-3 Suspendable Interface

package weblogic.connector.extensions;
import java.util.Properties;
import javax.resource.ResourceException;
import javax.resource.spi.ResourceAdapter;
/**
* Suspendable may be implemented by a ResourceAdapter JavaBean if it
* supports suspend, resume or side-by-side versioning
* @author Copyright (c) 2002 by BEA Systems, Inc. All Rights Reserved.
* @since November 14, 2003
*/
public interface Suspendable
{
/**
* Used to indicate that inbound communication is to be suspended/resumed
*/
int INBOUND = 1;
/**
* Used to indicate that outbound communication is to be suspended/resumed
*/
int OUTBOUND = 2;
/**
* Used to indicate that submission of Work is to be suspended/resumed
*/
int WORK = 4;
/**
* Used to indicate that INBOUND, OUTBOUND & WORK are to be suspended/resumed
*/
int ALL = 7;
/**
* May be used to indicate a suspend() operation
*/
int SUSPEND = 1;
/**
* May be used to indicate a resume() operation
*/
int RESUME = 2;
/**
* Request to suspend the activity specified. The properties may be null or
* specified according to RA-specific needs 
* @param type An int from 1 to 7 specifying the type of suspension being 
* requested (i.e. Suspendable.INBOUND, .OUTBOUND, .WORK or the sum of one
* or more of these, or the value Suspendable.ALL )
* @param props Optional Properties (or null) to be used for ResourceAdapter
* specific purposes
* @exception ResourceException If the resource adapter can't complete the
* request
*/
void suspend( int type, Properties props ) throws ResourceException;
/**
* Request to resume the activity specified. The Properties may be null or
* specified according to RA-specific needs
*
* @param type An int from 1 to 7 specifying the type of resume being
* requested (i.e. Suspendable.INBOUND, .OUTBOUND, .WORK or the sum of
* one or more of these, or the value Suspendable.ALL )
* @param props Optional Properties (or null) to be used for ResourceAdapter
* specific purposes
* @exception ResourceException If the resource adapter can't complete the
* request
*/
void resume( int type, Properties props ) throws ResourceException;
/**
*
* @param type An int from 1 to 7 specifying the type of suspend this inquiry
* is about (i.e. Suspendable.INBOUND, .OUTBOUND, .WORK or the sum of
* one or more of these, or the value Suspendable.ALL )
* @return true iff the specified type of suspend is supported
*/
boolean supportsSuspend( int type );
/**
* 
* Used to determine whether the specified type of activity is 
* currently suspended.
*
* @param type An int from 1 to 7 specifying the type of activity
* requested (i.e. Suspendable.INBOUND, .OUTBOUND, .WORK or the sum of
* one or more of these, or the value Suspendable.ALL )
* @return true iff the specified type of activity is suspened by this 
* resource adapter
*/
boolean isSuspended( int type );
/**
* Used to determine if this resource adapter supports the init() method used for
* resource adapter versioning (side-by-side deployment)
*
* @return true iff this resource adapter supports the init() method
*/
boolean supportsInit();
/**
* Used to determine if this resource adapter supports the startVersioning()
* method used for
* resource adapter versioning (side-by-side deployment)
*
* @return true iff this resource adapter supports the startVersioning() method
*/
boolean supportsVersioning();
/**
* Used by WLS to indicate to the current version of this resource adapter that 
* a new version of the resource adapter is being deployed. This method can
* be used by the old RA to communicate with the new RA and migrate services 
* from the old to the new.
* After being called, the ResourceAdapter is responsible for notifying the 
* Connector container via the ExtendedBootstrapContext.complete() method, that 
* it is safe to be undeployed.
*
* @param ra The new ResourceAdapter JavaBean
* @param props Properties associated with the versioning
* when it can be undeployed
* @exception ResourceException If something goes wrong
*/
void startVersioning( ResourceAdapter ra, 
Properties props ) throws ResourceException;
/**
* Used by WLS to inform a ResourceAdapter that it is a new version of an already
* deployed resource adapter. This method is called prior to start() so that
* the new resource adapter may coordinate its startup with the resource adapter
* it is replacing.
* @param ra The old version of the resource adapter that is currently running
* @param props Properties associated with the versioning operation
* @exception ResourceException If the init() fails.
*/
void init( ResourceAdapter ra, Properties props ) throws ResourceException;
}

Extended BootstrapContext

If, when a resource adapter is deployed, it has a resource adapter JavaBean specified in the resource-adapter-class element of its ra.xml descriptor, the WebLogic Server connector container calls the start() method on the resource adapter bean as required by JSR 322: Java EE Connector Architecture 1.6. The resource adapter code can use the BootstrapContext object that is passed in by the start() method to:

  • Obtain a WorkManager object for submitting Work instances

  • Create a Timer

  • Obtain an XATerminator for use in transaction inflow

These capabilities are all prescribed by Connector Architecture 1.6.

In addition to implementing the required javax.resource.spi.BootstrapContext, the BootstrapContext object passed to the resource adapter start() method also implements weblogic.connector.extensions.ExtendedBootstrapContext, which gives the resource adapter access to some additional WebLogic Server-specific extensions that enhance diagnostic capabilities and that also support Contexts and Dependency Injection (CDI). These extensions are described in the following sections:

Diagnostic Context ID

In the WebLogic Server Diagnostic Framework, a thread may have an associated diagnostic context. A request on the thread carries its diagnostic context throughout its lifetime, as it proceeds along its path of execution. The ExtendedBootstrapContext allows the resource adapter developer to set a diagnostic context payload consisting of a String that can be used, for example, to trace the execution of a request from an EIS all the way to a message endpoint.

This capability can serve a variety of diagnostic purposes. For example, you can set the String to the client ID or session ID on an inbound message from an EIS. During message dispatch, various diagnostics can be gathered to show the request flow through the system. As you develop your resource adapter classes, you can make use of the setDiagnosticContextID() and getDiagnosticContextID() methods for this purpose.

Note the following regarding the contents of the diagnostic context payload:

  • The payload can be viewed by other code in the same execution context, and it can also flow out of the process along with the Work instance. Therefore, you should ensure that the application does not include any sensitive data in the payload that, for example, could be returned by the getDiagnosticContextID() method.

  • The payload can be overwritten by other code in the same execution context. Therefore, the application must never have a dependency on a specific context ID being available in the payload. In addition, the application should also verify that the context ID in the payload matches what is expected before using it.

For more information about the diagnostic context, see Configuring and Using the Diagnostics Framework for Oracle WebLogic Server.

Dye Bits

The WebLogic Server diagnostic framework also provides the ability to dye a request. The ExtendedBootstrapContext allows you to set and retrieve four dye bits on the current thread for whatever diagnostic purpose the resource adapter developer chooses. For example, you might set priority of a request using the dye bits. For more information about request dyeing, see Configuring and Using the Diagnostics Framework for Oracle WebLogic Server.

Callback Capabilities

You can use the ExtendedBootstrapContext.complete() method as a callback to the connector container. For detailed information on this feature, see Redeploying Applications in a Production Environment in Deploying Applications to Oracle WebLogic Server.

Bean Validation

In its support of JSR 303: Bean Validation, WebLogic Server extends Java EE 6 by providing a module-level bean validation configuration file, which WebLogic Server uses to validate the resource adapter module.

There are circumstances in which you might want a resource adapter to perform validation on other bean instances that are managed by that resource adapter. Because a resource adapter does not have its own JNDI namespace, it cannot look up its own Validator and ValidatorFactory instances using JNDI. Instead, the resource adapter can inject those beans using CDI, or use the following methods on the ExtendedBootstrapContext interface to obtain instances of those beans:

  • getValidator()

  • getValidatorFactory()

BeanManager

To support JSR 299: Contexts and Dependency Injection for the Java EE Platform (CDI), WebLogic Server implements the getBeanManager method on the ExtendedBootstrapContext interface. A resource adapter can invoke this method to obtain its own BeanManager instance and perform CDI-style injection of managed beans inside the resource adapter.

Note:

Note the following restrictions:

  • The use of a resource adapter's BeanManager instance by a separate, caller thread is not supported.

  • You cannot use a BeanManager instance to manage the life cycle of resource adapter component beans.

For more information about using the getBeanManager method on the ExtendedBootstrapContext interface to use CDI, see Using Contexts and Dependency Injection in Resource Adapters.

Administered Object Uniqueness

Connector Architecture 1.6 allows a resource adapter to have multiple administered object classes that implement the same interface. However, there must be no more than one administered object definition with the same interface and class name combination (see Section 20.4.1, Resource Adapter Provider in JSR 322: Java EE Connector Architecture 1.6). The adminobject-type-uniqueness constraint has been added to the schema definition for the ra.xml file to define the adminobject-interface and adminobject-class combination.

In previous releases of WebLogic Server, the mapping of an admin object group defined in weblogic-ra.xml to the corresponding admin object defined in ra.xml was based on the admin object interface only. However, to support multiple admin object classes that have the same interface, WebLogic Server includes the optional admin-object-class sub-element of the admin-object-group element in weblogic-ra.xml. You can use the admin-object-class sub-element to define an admin object interface and class combination that WebLogic Server is able to map to the corresponding admin object defined in ra.xml.

When mapping an admin object group, WebLogic Server uses the following rules, which also ensure backward compatibility with 1.0 and 1.5 adapters:

  • If the admin object group defined in weblogic-ra.xml includes both an admin object interface and class, WebLogic Server attempts to match that interface and class to the corresponding admin object definition in ra.xml.

  • If the admin object group defined in weblogic-ra.xml includes only one admin object interface, and more than one matching admin object interface is defined in ra.xml, WebLogic Server generates an error.

  • If the admin object group defined in weblogic-ra.xml includes only one admin object interface, and only one matching admin object interface is defined in ra.xml, that specific admin object interface is used.