We will now write and deploy a new service that exposes all the WS-ResourceProperty portTypes. Our client application will, in turn, make a call to some of these portTypes. For simplicity, our service will be based on the example presented in Chapter 3, Writing Your First Stateful Web Service in 5 Simple Steps (the example that uses ServiceResourceHome to confine our implementation to a single class). However, the steps described in this chapter are equally valid for the other two types of implementations we have seen in the previous two chapters (singleton resource homes, and factory/instance services).
In the previous chapters, we were always able to reuse our original WSDL file because we were only modifying implementation details (for example, changing the implementation from a singleton resource home to a factory/service approach). However, in this chapter we do have to use a new WSDL file because we want to extend from new portTypes, which necessarily changes our service's interface. However, our changes will be minimal:
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="MathService"
targetNamespace="http://www.globus.org/namespaces/examples/core/MathService_instance_rp"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://www.globus.org/namespaces/examples/core/MathService_instance"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:wsrpw="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
xmlns:wsdlpp="http://www.globus.org/namespaces/2004/10/WSDLPreprocessor"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:import
namespace=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
location="../../wsrf/properties/WS-ResourceProperties.wsdl" />
<-- ... -->
<portType name="MathPortType"
wsdlpp:extends="wsrpw:GetResourceProperty
wsrpw:GetMultipleResourceProperties
wsrpw:SetResourceProperties
wsrpw:QueryResourceProperties"
wsrp:ResourceProperties="tns:MathResourceProperties">
<operation name="add">
<input message="tns:AddInputMessage"/>
<output message="tns:AddOutputMessage"/>
</operation>
<operation name="subtract">
<input message="tns:SubtractInputMessage"/>
<output message="tns:SubtractOutputMessage"/>
</operation>
</portType>
</definitions>
![]() | |
This is part of file
|
Since we have added a new interface, we need to map the new WSDL namespaces to Java packages (as described in Section 3.1.3, “Namespace mappings”)
http\://www.globus.org/namespaces/examples/core/MathService_instance_rp=
org.globus.examples.stubs.MathService_instance_rp
http\://www.globus.org/namespaces/examples/core/MathService_instance_rp/bindings=
org.globus.examples.stubs.MathService_instance_rp.bindings
http\://www.globus.org/namespaces/examples/core/MathService_instance_rp/service=
org.globus.examples.stubs.MathService_instance_rp.service
![]() | |
These three lines must be present in
|
The implementation files only require minimal changes. The only noteworthy change is that we no longer need to implement the getValueRP operation. In general, using the WS-ResourceProperties portTypes doesn't require that we add any extra code to our Java files.
![]() | |
This QNames interface for this example is
|
![]() | |
This service class for this example is
|
To be able to use the WS-ResourceProperties portTypes we need to modify our WSDD file to make sure that our service relies on the Globus-supplied operation providers for those portTypes.
<?xml version="1.0" encoding="UTF-8"?>
<deployment name="defaultServerConfig"
xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<service name="examples/core/rp/MathService" provider="Handler" use="literal" style="document">
<parameter name="className" value="org.globus.examples.services.core.rp.impl.MathService"/>
<wsdlFile>share/schema/examples/MathService_instance_rp/Math_service.wsdl</wsdlFile>
<parameter name="allowedMethods" value="*"/>
<parameter name="handlerClass" value="org.globus.axis.providers.RPCProvider"/>
<parameter name="scope" value="Application"/>
<parameter name="providers" value="GetRPProvider GetMRPProvider SetRPProvider QueryRPProvider"/>
<parameter name="loadOnStartup" value="true"/>
</service>
</deployment>
![]() | |
This is file
|
![]() | Operation Providers |
|---|---|
GT4 Core uses a design pattern called operation providers that will make our lives as programmers much easier. To put it quite simply, an operation provider is a Java class, providing a set of operations, that we can easily plug into our service. For example, remember that the WSDL file we've used in the previous chapters included the following:
<portType name="MathPortType"
wsdlpp:extends="wsrpw:GetResourceProperty"
wsrp:ResourceProperties="tns:MathResourceProperties">
We used the <parameter name="providers" value="GetRPProvider"/> In the following chapters, each time we want our service to provide standard functionality specified in the WSRF specs, we will simply make our service extend from a standard WSRF portType and then 'plug in' a Globus operation provider that implements that portType. |
The JNDI deployment file, on the other hand, doesn't require any changes.
Build the service:
./globus-build-service.sh rp
And deploy it:
globus-deploy-gar $EXAMPLES_DIR/org_globus_examples_services_core_rp.gar
Our client application will make calls to some of the WS-ResourceProperties portTypes. The next example will use more complex resource properties and then we will see how to invoke the rest of the portTypes.
The code for this client is rather lengthy, so instead of seeing all the code all at once, we are going to run the client first, and then take a close look at what happens at each moment.
![]() | |
This source code for the client is
|
Compile the client:
javac \ -classpath ./build/stubs/classes/:$CLASSPATH \ org/globus/examples/clients/MathService_instance_rp/Client.java
And run it:
java \ -classpath ./build/stubs/classes/:$CLASSPATH \ org.globus.examples.clients.MathService_instance_rp.Client \ http://127.0.0.1:8080/wsrf/services/examples/core/rp/MathService
The full output of the client should be the following:
Value RP: 0 LastOp RP: NONE Value RP: 10 LastOp RP: ADDITION Value RP: 100 LastOp RP: ADDITION Value: 100 LastOp: ADDITION
Let's take a close look at what happens in each of these three blocks.
Value RP: 0 LastOp RP: NONE Value RP: 10 LastOp RP: ADDITION
The first block of code prints out the initial values of the Value and LastOp RP's using the getResourceProperty operation, performs an addition, and then prints out the RP's again. All the getResourceProperty code is placed inside a printResourceProperties method.
printResourceProperties(math); math.add(10); printResourceProperties(math);
Let's take a close look at what happens in the printResourceProperties method:
/*
* This method prints out MathService's resource properties by using the
* GetResourceProperty operation.
*/
private void printResourceProperties(MathPortType math) throws Exception {
GetResourcePropertyResponse valueRP, lastOpRP, lastLogRP;
String value, lastOp, lastLog;
valueRP = math.getResourceProperty(MathQNames.RP_VALUE);
lastOpRP = math.getResourceProperty(MathQNames.RP_LASTOP);
value = valueRP.get_any()[0].getValue();
lastOp = lastOpRP.get_any()[0].getValue();
System.out.println("Value RP: " + value);
System.out.println("LastOp RP: " + lastOp);
}
Value RP: 100 LastOp RP: ADDITION
The second block of code updates the value of the Value RP using the SetResourceProperties operation and requesting an Update action. All the update code is placed inside a updateRP method.
updateRP(endpoint, MathQNames.RP_VALUE, "100"); printResourceProperties(math);
Now, let's see how the update operation is actually carried out:
/*
* This method updates resource property "rpQName" in the WS-Resource
* pointed at by the endpoint reference "epr" with the new value "value".
*/
private void updateRP(EndpointReferenceType epr, QName rpQName, String value)
throws Exception {
WSResourcePropertiesServiceAddressingLocator locator = new WSResourcePropertiesServiceAddressingLocator();
SetResourceProperties_PortType port = locator
.getSetResourcePropertiesPort(epr);
UpdateType update = new UpdateType();
MessageElement msg = new MessageElement(rpQName, value);
update.set_any(new MessageElement[] { msg });
SetResourceProperties_Element request = new SetResourceProperties_Element();
request.setUpdate(update);
port.setResourceProperties(request);
}
Value: 100 LastOp: ADDITION
The third, and last, block of code prints out the values of the Value and LastOp RP's using the GetMultipleResourceProperties operation. All the GetMultipleResourceProperties code is placed inside a printMultipleResourceProperties method.
printMultipleResourceProperties(math);
/*
* This method prints out MathService's resource properties by using the
* GetMultipleResourceProperties operation.
*/
private void printMultipleResourceProperties(MathPortType math)
throws Exception {
GetMultipleResourceProperties_Element request;
GetMultipleResourcePropertiesResponse response;
QName[] resourceProperties = new QName[] { MathQNames.RP_VALUE,
MathQNames.RP_LASTOP };
request = new GetMultipleResourceProperties_Element(resourceProperties);
response = math.getMultipleResourceProperties(request);
for(int i=0; i<response.get_any().length;i++)
{
String name = response.get_any()[i].getLocalName();
String value = response.get_any()[i].getValue();
System.out.println(name +": " + value);
}
}