Applications interact with the work area service by implementing
the UserWorkArea interface. This interface defines all of the methods
used to create, manipulate, and terminate work areas.
About this task
package com.ibm.websphere.workarea;
public interface UserWorkArea {
void begin(String name);
void complete() throws NoWorkArea, NotOriginator;
String getName();
String[] retrieveAllKeys();
void set(String key, java.io.Serializable value)
throws NoWorkArea, NotOriginator, PropertyReadOnly;
void set(String key, java.io.Serializable value, PropertyModeType mode)
throws NoWorkArea, NotOriginator, PropertyReadOnly;
java.io.Serializable get(String key);
PropertyModeType getMode(String key);
void remove(String key)
throws NoWorkArea, NotOriginator, PropertyFixed;
}
Attention: Enterprise JavaBeans (EJB)
applications can use the UserWorkArea interface only within the implementation
of methods in either the remote or local interface, or both; likewise,
servlets can use the interface only within the service method of the
HTTPServlet class. Use of work areas within any life cycle method
of a servlet or enterprise bean is considered a deviation from the
work area programming model and is not supported.
The work
area service defines the following exceptions for use with the UserWorkArea
interface:
- NoWorkArea
- Raised when a request requires an associated work area but none
is present.
- NotOriginator
- Raised when a request attempts to manipulate the contents of an
imported work area.
- PropertyReadOnly
- Raised when a request attempts to modify a read-only or fixed
read-only property.
- PropertyFixed
- Raised by the remove method when the designated property has one
of the fixed modes.
- Access a partition by either:
- Accessing the UserWorkArea partition, to access the UserWorkArea
partition.
- Accessing a user-defined work area partition, to access a
user-defined work area.
The following steps use the UserWorkArea partition as an example;
however, you can use a user-defined partition in the same way.
- Begin a new work area.
Use the begin method
to create a new work area and associate it with the calling thread.
A work area is scoped to the thread that began the work area and is
not accessible by multiple threads. The begin method takes a string
as an argument; the string is used to name the work area. The argument
must not be null, which causes the java.lang.NullPointer exception
to be raised. In the following code example, the application begins
a new work area with the name SimpleSampleServlet:
public class SimpleSampleServlet {
...
try {
...
userWorkArea = (UserWorkArea)jndi.lookup(
"java:comp/websphere/UserWorkArea");
}
...
userWorkArea.begin("SimpleSampleServlet");
...
}
The begin method is also used to create nested work
areas; if a work area is associated with a thread when the begin method
is called, the method creates a new work area nested within the existing
work area.
The work area service makes no use of the names
associated with work areas; You can name work areas in any way that
you choose. Names are not required to be unique, but the usefulness
of the names for debugging is enhanced if the names are distinct and
meaningful within the application. Applications can use the getName
method to return the name associated with a work area by the begin
method.
- Set properties in the work area.
An application
with a current work area can insert properties into the work area
and retrieve the properties from the work area. The UserWorkArea interface
provides two set methods for setting properties and a get method for
retrieving properties. The two-argument set method inserts the property
with the property mode of normal. The three-argument set method takes
a property mode as the third argument. Both set methods take the key
and the value as arguments. The key is a String; the value is an object
of the type java.io.Serializable. None of the arguments can be null,
which causes the java.lang.NullPointer exception to be raised.
The SimpleSample application below uses objects of two
classes, the SimpleSampleCompany class and the SimpleSampleProperty
class, as values for properties. The SimpleSampleCompany class is
used for the site identifier, and the SimpleSamplePriority class is
used for the priority. These classes are shown in following code example:
public class SimpleSampleServlet {
...
userWorkArea.begin("SimpleSampleServlet");
try {
// Set the site-identifier (default is Main).
userWorkArea.set("company",
SimpleSampleCompany.Main, PropertyModeType.read_only);
// Set the priority.
userWorkArea.set("priority", SimpleSamplePriority.Silver);
}
catch (PropertyReadOnly e) {
// The company was previously set with the read-only or
// fixed read-only mode.
...
}
catch (NotOriginator e) {
// The work area originated in another process,
// so it can't be modified here.
...
}
catch (NoWorkArea e) {
// There is no work area begun on this thread.
...
}
// Do application work.
...
}
The get method takes the key as an argument and returns
a Java Serializable object as the value associated
with the key. For example, to retrieve the value of the company key
from the work area, the code example above uses the get method on
the work area to retrieve the value.
Setting property modes.
The two-argument set method on the UserWorkArea interface takes a
key and a value as arguments and inserts the property with the default
property mode of normal. To set a property with a different mode,
applications must use the three-argument set method, which takes a
property mode as the third argument. The values used to request the
property modes are as follows:
- Normal: PropertyModeType.normal
- Fixed normal: PropertyModeType.fixed_normal
- Read-only: PropertyModeType.read_only
- Fixed read-only: PropertyModeType.fixed_readonly
- Manage local work with a work area.
- Complete the work area.
After an application
has finished using a work area, it must complete the work area by
calling the complete method on the UserWorkArea interface. This terminates
the association with the calling thread and destroys the work area.
If the complete method is called on a nested work area, the nested
work area is terminated and the parent work area becomes the current
work area. If there is no work area associated with the calling thread,
a NoWorkArea exception is created. Every work area must be completed,
and work areas can be completed only by the originating process. For
example, if a server attempts to call the complete method on a work
area that originated in a client, a NotOriginator exception is created.
Work areas created in a server process are never propagated back to
an invoking client process.
Attention: The work area
service claims full local-remote transparency. Even if two beans happen
to be deployed in the same server, and therefore the same JVM and
process, a work area begun on an invocation from another is completed
and the bean in which the request originated is always in the same
state after any remote call.
The following
code example shows the completion of the work area created in the
client application.
public class SimpleSampleServlet {
...
userWorkArea.begin("SimpleSampleServlet");
userWorkArea.set("company",
SimpleSampleCompany.Main, PropertyModeType.read_only);
userWorkArea.set("priority", SimpleSamplePriority.Silver);
...
// Do application work.
...
// Terminate the work area.
try {
userWorkArea.complete();
}
catch (NoWorkArea e) {
// There is no work area associated with this thread.
...
}
catch (NotOriginator e) {
// The work area was imported into this process.
...
}
...
}
The following code example shows the sample application
completing the nested work area that it created earlier in the remote
invocation.
public class SimpleSampleBeanImpl implements SessionBean {
public String [] test() {
...
// Begin a nested work area.
userWorkArea.begin("SimpleSampleBean");
try {
userWorkArea.set("company",
SimpleSampleCompany.London_Development);
}
catch (NotOriginator e) {
}
SimpleSampleCompany company =
(SimpleSampleCompany) userWorkArea.get("company");
SimpleSamplePriority priority =
(SimpleSamplePriority) userWorkArea.get("priority");
// Complete all nested work areas before returning.
try {
userWorkArea.complete();
}
catch (NoWorkArea e) {
}
catch (NotOriginator e) {
}
}
}
Example
Work area object types. In the
following example, the client creates a work area and inserts two
properties into the work area: a site identifier and a priority. The
site-identifier is set as a read-only property; the client does not
allow recipients of the work area to override the site identifier.
This property consists of the key company and a static instance of
a SimpleSampleCompany object. The priority property consists of the
key priority and a static instance of a SimpleSamplePriority object.
The object types are defined as shown in the following code example:
public static final class SimpleSampleCompany {
public static final SimpleSampleCompany Main;
public static final SimpleSampleCompany NewYork_Sales;
public static final SimpleSampleCompany NewYork_Development;
public static final SimpleSampleCompany London_Sales;
public static final SimpleSampleCompany London_Development;
}
public static final class SimpleSamplePriority {
public static final SimpleSamplePriority Platinum;
public static final SimpleSamplePriority Gold;
public static final SimpleSamplePriority Silver;
public static final SimpleSamplePriority Bronze;
public static final SimpleSamplePriority Tin;
}
The client then makes an invocation on a remote object.
The work area is automatically propagated; none of the methods on
the remote object take a work area argument. On the remote side, the
request is first handled by the SimpleSampleBean; the bean first reads
the site identifier and priority properties from the work area. The
bean then intentionally attempts, and fails, both to write directly
into the imported work area and to override the read-only site-identifier
property.
The SimpleSampleBean successfully begins a nested
work area, in which it overrides the client's priority, then calls
another bean, the SimpleSampleBackendBean. The SimpleSampleBackendBean
reads the properties from the work area, which contains the site identifier
set in the client and priority set in the SimpleSampleBean. Finally,
the SimpleSampleBean completes its nested work area, writes out a
message based on the site-identifier property, and returns.
Using the work area partition manager. The
following code example illustrates the use of the work area partition
manager interface. The sample illustrates how to create and retrieve
a work area partition programmatically`. Please note that programmatically
creating a work area partition is only available on the Java Platform, Enterprise Edition (Java EE) client. To create a work area partition
on the server one must use the administrative console. Refer to the
Work area partition service article for configuration parameters available
to configure a partition.
import com.ibm.websphere.workarea.WorkAreaPartitionManager;
import com.ibm.websphere.workarea.UserWorkArea;
import com.ibm.websphere.workarea.PartitionAlreadyExistsException;
import com.ibm.websphere.workarea.NoSuchPartitionException;
import java.lang.IllegalAccessError;
import java.util.Properties;
import javax.naming.InitialContext;
//This sample demonstrates how to retrieve an instance of the
//WorkAreaPartitionManager implementation and how to use that
//instance to create a WorkArea partition and retrieve a partition.
//NOTE: Creating a partition in the way listed below is only available
//on a J2EE client. To create a partition on the server use the
//WebSphere administrative console. Retrieving a WorkArea
//partition is performed in the same way on both client and server.
public class Example {
//The name of the partition to create/retrieve
String partitionName = "myPartitionName";
//The name in java naming the WorkAreaPartitionManager instance is bound to
String jndiName = "java:comp/websphere/WorkAreaPartitionManager";
//On a J2EE client a user would create a partition as follows:
public UserWorkArea myCreate(){
//Variable to hold our WorkAreaPartitionManager reference
WorkAreaPartitionManager partitionManager = null;
//Get an instance of the WorkAreaPartitionManager implementation
try {
InitialContext initialContext = new InitialContext();
partitionManager = (WorkAreaPartitionManager) initialContext.lookup(jndiName);
} catch (Exception e) { }
//Set the properties to configure our WorkArea partition
Properties props = new Properties();
props.put("maxSendSize","12345");
props.put("maxReceiveSize","54321");
props.put("Bidirectional","true");
props.put("DeferredAttributeSerialization","true");
//Variable used to hold the newly created WorkArea Partition
UserWorkArea myPartition = null;
try{
//This is the way to create a partition on the J2EE client. Use the
//WebSphere Administrative Console to create a WorkArea Partition
//on the server.
myPartition = partitionManager.createWorkAreaPartition(partitionName,props);
}
catch (PartitionAlreadyExistsException e){ }
catch (IllegalAccessException e){ }
return myPartition;
}
//. . . .
//In order to retrieve a WorkArea partition at some time later or
//from some other class, do the following (from client or server):
public UserWorkArea myGet(){
//Variable to hold our WorkAreaPartitionManager reference
WorkAreaPartitionManager partitionManager = null;
//Get an instance of the WorkAreaPartitionManager implementation
try {
InitialContext initialContext = new InitialContext();
partitionManager = (WorkAreaPartitionManager) initialContext.lookup(jndiName);
} catch (Exception e) { }
//Variable used to hold the retrieved WorkArea partition
UserWorkArea myPartition = null;
try{
myPartition = partitionManager.getWorkAreaPartition(partitionName);
}catch(NoSuchPartitionException e){ }
return myPartition;
}
}