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); } }