11 Programming Context Propagation

The following sections describe how to use the context propagation APIs in your applications:

Understanding Context Propagation

Context propagation allows programmers to associate information with an application which is then carried along with every request. Furthermore, downstream components can add or modify this information so that it can be carried back to the originator. Context propagation is also known as work areas, work contexts, or application transactions.

Common use-cases for context propagation are any type of application in which information needs to be carried outside the application, rather than the information being an integral part of the application. Examples of these use cases include diagnostics monitoring, application transactions, and application load-balancing. Keeping this sort of information outside of the application keeps the application itself clean with no extraneous API usage and also allows the addition of information to read-only components, such as 3rd party components.

Programming context propagation has two parts: first you code the client application to create a WorkContextMap and WorkContext, and then add user data to the context, and then you code the invoked application itself to get and possibly use this data. The invoked application can be of any type: EJB, Web Service, servlet, JMS topic or queue, and so on. See Programming Context Propagation: Main Steps for details.

The WebLogic context propagation APIs are in the weblogic.workarea package. The following table describes the main interfaces and classes.

Table 11-1 Interfaces and classes of the WebLogic Context Propagation API

Interface or Class Description

WorkContextMap Interface

Main context propagation interface used to tag applications with data and propagate that information via application requests. WorkContextMaps is part of the client or application's JNDI environment and can be accessed through JNDI by looking up the name java:comp/WorkContextMap.

WorkContext Interface

Interface used for marshaling and unmarshaling the user data that is passed along with an application. This interface has four implementing classes for marshaling and unmarshaling the following types of data: simple 8-bit ASCII contexts (AsciiWorkContext), long contexts (LongWorkContext), Serializable context (SerializableWorkContext), and String contexts (StringWorkContext).

WorkContext has one subinterface, PrimitiveWorkContext, used to specifically marshal and unmarshal a single primitive data item.

WorkContextOutput/Input Interfaces

Interfaces representing primitive streams used for marshaling and unmarshaling, respectively, WorkContext implementations.

PropagationMode Interface

Defines the propagation properties of WorkContexts. Specifies whether the WorkContext is propagated locally, across threads, across RMI invocations, across JMS queues and topics, or across SOAP messages. If not specified, default is to propagate data across remote and local calls in the same thread.

PrimitiveContextFactory Class

Convenience class for creating WorkContexts that contain only primitive data.


For the complete API documentation about context propagation, see the weblogic.workarea Javadocs.

Programming Context Propagation: Main Steps

The following procedure describes the high-level steps to use context propagation in your application. It is assumed in the procedure that you have already set up your iterative development environment and have an existing client and application that you want to update to use context propagation by using the weblogic.workarea API.

  1. Update your client application to create the WorkContextMap and WorkContext objects and then add user data to the context.

    See Programming Context Propagation in a Client.

  2. If your client application is standalone (rather than running in a Java EE component deployed to WebLogic Server), ensure that its CLASSPATH includes the Java EE application client, also called the thin client.

    See Programming Stand-alone Clients for Oracle WebLogic Server.

  3. Update your application (EJB, Web Service, servlet, and so on) to also create a WorkContextMap and then get the context and user data that you added from the client application.

    See Programming Context Propagation in an Application.

Programming Context Propagation in a Client

The following sample Java code shows a standalone Java client that invokes a Web Service; the example also shows how to use the weblogic.workarea.* context propagation APIs to associate user information with the invoke. The code relevant to context propagation is shown in bold and explained after the example.

For the complete API documentation about context propagation, see the weblogic.workarea Javadocs.

Note:

See Getting Started With JAX-WS Web Services for Oracle WebLogic Server for information on creating Web Services and client applications that invoke them.
package examples.workarea.client;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.Stub;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import weblogic.workarea.WorkContextMap;
import weblogic.workarea.WorkContext;
import weblogic.workarea.PrimitiveContextFactory;
import weblogic.workarea.PropagationMode;
import weblogic.workarea.PropertyReadOnlyException;
/**
 * This is a simple standalone client application that invokes the
 * the <code>sayHello</code> operation of the WorkArea Web service.
 *
 */
public class Main {
  public final static String SESSION_ID= "session_id_key";
  public static void main(String[] args)
      throws ServiceException, RemoteException, NamingException, PropertyReadOnlyException{
    WorkAreaService service = new WorkAreaService_Impl(args[0] + "?WSDL");
    WorkAreaPortType port = service.getWorkAreaPort();
    WorkContextMap map = (WorkContextMap)new InitialContext().lookup("java:comp/WorkContextMap");
    WorkContext stringContext = PrimitiveContextFactory.create("A String Context");
    // Put a string context
    map.put(SESSION_ID, stringContext, PropagationMode.SOAP);
    try {
      String result = null;
      result = port.sayHello("Hi there!");
      System.out.println( "Got result: " + result );
    } catch (RemoteException e) {
      throw e;
    }
  }
}

In the preceding example:

  • The following code shows how to import the needed weblogic.workarea.* classes, interfaces, and exceptions:

    import weblogic.workarea.WorkContextMap;
    import weblogic.workarea.WorkContext;
    import weblogic.workarea.PrimitiveContextFactory;
    import weblogic.workarea.PropagationMode;
    import weblogic.workarea.PropertyReadOnlyException;
    
  • The following code shows how to create a WorkContextMap by doing a JNDI lookup of the context propagation-specific JNDI name java:comp/WorkContextMap:

    WorkContextMap map = (WorkContextMap)
          new InitialContext().lookup("java:comp/WorkContextMap");
    
  • The following code shows how to create a WorkContext by using the PrimitiveContextFactory. In this example, the WorkContext consists of the simple String value A String Context. This String value is the user data that is passed to the invoked Web Service.

    WorkContext stringContext =
         PrimitiveContextFactory.create("A String Context");
    
  • Finally, the following code shows how to add the context data, along with the key SESSION_ID, to the WorkContextMap and associate it with the current thread. The PropagationMode.SOAP constant specifies that the propagation happens over SOAP messages; this is because the client is invoking a Web Service.

    map.put(SESSION_ID, stringContext, PropagationMode.SOAP);
    

Programming Context Propagation in an Application

The following sample Java code shows a simple Java Web Service (JWS) file that implements a Web Service. The JWS file also includes context propagation code to get the user data that is associated with the invoke of the Web Service. The code relevant to context propagation is shown in bold and explained after the example.

For the complete API documentation about context propagation, see the weblogic.workarea Javadocs.

Note:

See Getting Started With JAX-WS Web Services for Oracle WebLogic Server for information on creating Web Services and client applications that invoke them.
package examples.workarea;
import javax.naming.InitialContext;
// Import the Context Propagation classes
import weblogic.workarea.WorkContextMap;
import weblogic.workarea.WorkContext;
import javax.jws.WebMethod;
import javax.jws.WebService;
import weblogic.jws.WLHttpTransport;
@WebService(name="WorkAreaPortType", 
            serviceName="WorkAreaService",
             targetNamespace="http://example.org")
@WLHttpTransport(contextPath="workarea", 
                 serviceUri="WorkAreaService",
                  portName="WorkAreaPort")
/**
 * This JWS file forms the basis of simple WebLogic
 * Web Service with a single operation: sayHello
 *
 */
public class WorkAreaImpl {
  public final static String SESSION_ID = "session_id_key";
  @WebMethod()
  public String sayHello(String message) {
   try {
    WorkContextMap map = (WorkContextMap) new InitialContext().lookup("java:comp/WorkContextMap");
    WorkContext localwc = map.get(SESSION_ID);
    System.out.println("local context: " + localwc);
    System.out.println("sayHello: " + message);
    return "Here is the message: '" + message + "'";
   } catch (Throwable t) {
    return "error";
   }
  }
}

In the preceding example:

  • The following code shows how to import the needed context propagation APIs; in this case, only the WorkContextMap and WorkContext interfaces are needed:

    import weblogic.workarea.WorkContextMap;
    import weblogic.workarea.WorkContext;
    
  • The following code shows how to create a WorkContextMap by doing a JNDI lookup of the context propagation-specific JNDI name java:comp/WorkContextMap:

    WorkContextMap map = (WorkContextMap)
        new InitialContext().lookup("java:comp/WorkContextMap");
    
  • The following code shows how to get context's user data from the current WorkContextMap using a key; in this case, the key is the same one that the client application set when it invoked the Web Service: SESSION_ID:

    WorkContext localwc = map.get(SESSION_ID);