5.2. Implementing the WS-Resource factory pattern in GT4

Implementing this design pattern in GT4 is actually not too complicated. In fact, it is very similar to the example seen in the previous chapter, with two main differences, highlighted in Figure 5.2, “Relationships between the Factory Service, the Instance Service, the Resource Home, and the Resource” (compare with Figure 4.1, “Relationships between the Service, the Resource Home, and the Resource”)

Figure 5.2. Relationships between the Factory Service, the Instance Service, the Resource Home, and the Resource

Relationships between the Factory Service, the Instance Service, the Resource Home, and the Resource

So, for this example, we will have four Java classes (plus the MathQNames interface)

Before seeing the actual code, a good way of seeing what role each class plays is to see how they interact. For now, don't worry about all the deployment details. Just imagine that we actually have our two services (factory and instance) up and ready to accept invocations from a client class, and that the service class has access to the resource home and that the resource home, in turn, has access to a bunch of resource objects. Let's start with the creation of a new resource, shown in Figure 5.3, “Sequence diagram for resource creation”.

Figure 5.3. Sequence diagram for resource creation

Sequence diagram for resource creation
  1. Our client only needs to know the URI of the factory service (MathFactoryService). With it, it can invoke the createResource operation. This will return an endpoint reference containing the URI of the instance service, along with the key of the recently created resource.

  2. So, the factory service has to create a new resource. This necessarily has to be done through the resource home, which is in charge of managing all the resources. However, we have to locate our resource home first. Fortunately, this is quite easy since we can delegate this task on a Globus-supplied class called ResourceContext. In the previous chapter, we used this class to retrieve the service's singleton resource. It can also be used to obtain a reference to the service's resource home.

  3. Now that we have the resource home, we can ask it to create the new resource. The creation method returns an object of type ResourceKey. This is the resource identifier which we need to create the endpoint reference we'll be returning to the client.

  4. The resource home will take care of actually creating a new MathResource instance.

  5. Next, the resource home will add the new MathResource instance to its internal list of resources. This list will allow us to access any resource if we know that resource's identifier.

Once the createResource call has finished, the client will have the WS-Resource's endpoint reference. In all future calls, this endpoint reference will be passed along transparently in all our invocations. In other words, when we call add or subtract, the service class will know what resource we're referring to. So, let's take a close look at what happens when we invoke the add operation, as shown in Figure 5.4, “Sequence diagram for WS-Resource invocation”.

Figure 5.4. Sequence diagram for WS-Resource invocation

Sequence diagram for WS-Resource invocation
  1. The client invokes the add operation in the instance service (MathService).

  2. However, the add operation is stateless. It needs to retrieve a resource to actually work. The resource identifier is in the endpoint reference that is included in the invocation. Fortunately, the ResourceContext helper class once again shields us from all the potential nastiness. It will be in charge of reading the EPR and finding the resource it refers to.

  3. However, it's interesting to note that, internally, ResourceContext uses the ResourceHome to find the resource.

  4. Once we have the resource, the instance service can access all its state information, such as the "Value" and the "LastOp" resource properties. First of all, we will access the "Value" resource property. As in the example seen in the previous chapter, our resource (MathResource) will allow us to modify the RP's using get/set methods (in this case, with a simple getValue() method).

  5. Once we've modified the value, we have to make sure we commit the change in the resource (in our case, using setValue()). Otherwise, that bit of state information won't be remembered.

  6. Finally, we use the setLastOp() method in the resource to modify the LastOp resource property to equal "ADDITION".

Don't worry if you're a bit confused. When we actually start coding all this, it'll probably seem clearer (even so, you might want to review these diagrams once we've coded the full example).