16 Programming Context Propagation

Learn how to use the context propagation APIs in WebLogic Server applications.

This chapter includes the following sections:

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.

WebLogic context propagation associates named WorkContext entries with the current thread through a WorkContextMap. For supported invocation paths, entries travel with a request according to their propagation modes and applicable propagation policies. Supported request/response paths can return updated entries to the caller.

Common use-cases for context propagation are any type of application in which information, usually related to the request, needs to be carried outside the application or to another 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. The ability of context propagation to tie information to a request greatly simplifies managing such data, in contrast to maintaining a map of request data in each application and then implementing custom code to transmit such information between applications or threads. The mechanism is also called work areas or work contexts. It carries contextual metadata; it does not by itself begin, commit or roll back a Jakarta Transaction.

However, context propagation can occur within an application. For example, if an application submits work through a Work Manager, part of the processing occurs in different threads. Context propagation uses a PropagationMode to carry information to other threads.

Include PropagationMode.WORK when the entry must be copied into supported Work execution.

Programming context propagation has two parts: obtain the current WorkContextMap through the documented JNDI lookup and create WorkContext values in the client, then retrieve and use the entries in the invoked application. Supported uses include EJBs, servlets, Web services and JMS topics or queues. 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 16-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. WorkContextMap 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

WorkContext defines readContext and writeContext for marshaling and unmarshaling context values. Built-in value implementations include AsciiWorkContext, LongWorkContext, StringWorkContext and SerializableWorkContext. WorkContext itself does not declare get(). Its PrimitiveWorkContext subinterface exposes the contained value through Object get(); check the context and contained-value types before casting.

WorkContextOutput/Input Interfaces

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

PropagationMode Interface

Defines the propagation properties of WorkContext entries. The put(key, value) overload uses DEFAULT, which equals GLOBAL = RMI | JMS_QUEUE | SOAP | MIME_HEADER in this release. It does not include WORK or JMS_TOPIC. Combine required flags with bitwise OR, for example SOAP | WORK when the supported path must carry the entry both over SOAP and into Work instances. LOCAL alone confines propagation to the current thread; ONEWAY suppresses return propagation to the caller.

PrimitiveContextFactory Class

Convenience factory for built-in context values: create(String), create(long), createASCII(String), create(Serializable), and createMutable(Serializable). The String/long overloads create the corresponding built-in contexts. Serializable forms can throw IOException and are opaque to underlying protocols.

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

Programming Context Propagation: Main Steps

You can associate information to a request on a client, retrieve that information on the server, and then retrieve the value updated by the server instance using context propagation.

The following procedure describes the high-level steps to use context propagation with WebLogic Server. This example demonstrates how to associate information to a request on a client, how to retrieve that information on the server, and then how to retrieve the value updated by the server instance. 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.
  2. If your client application is standalone (rather than running in a Jakarta EE component deployed to WebLogic Server), ensure that its CLASSPATH includes the Jakarta EE application client, also called the thin client.
  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.

Programming Context Propagation in a Client

You can program context propagation to get “associated” user information when a client invokes an application.

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 Developing 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 your 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{
    YourWorkAreaService service = new YourWorkAreaService(args[0] + "?WSDL");
    YourWorkAreaPortType 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;
    
  • Substitute your implementation of the WorkArea service and port for your Web service for YourWorkAreaService and YourWorkAreaPortType.

  • 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");
    
  • The following code saves the stringContext under the SESSION_ID key in the WorkContextMap. Specifying the propagation mode of SOAP causes the propagation of the stringContext along any SOAP message sent to servers supporting context propagation.

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

Programming Context Propagation in an Application

You can program context propagation to get the user data and other associated information when the applications are invoked.

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 Developing 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;
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 WorkContextAwareWebService {
  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);
WorkContext modifiedLocalWC = PrimitiveContextFactory.create(localwc.get() + " could be replaced by a new value...");
    map.put(SESSION_ID, newLocalWC, PropagationMode.SOAP);
    System.out.println("local context: " + localwc);
    System.out.println("sayHello: " + message);
    return "The server received message: " + message + ", with SESSION_ID: " + localwc;
   } 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 propagation mode is SOAP only, meaning that propagation occurs both to the server with the request and to the client with the response. The following code shows how the server instance could modify the stringContext:

    WorkContext modifiedLocalWC = PrimitiveContextFactory.create(localwc.get() + " could be replaced by a new value...");
    
  • The following code replaces the work context with an updated value. When retrieving SESSION_ID on the client after the server returns the response, the value updated by the server is now present on the client.

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