1 開始前
該文檔針對Windows平臺已經安裝完ws-core-4.0.x的用戶。在繼續進行之前保證已經設置環境變量GLOBUS_LOCATION,指向ws-core-4.0.x的安裝目錄(在我的系統中為D:\ws-core-4.0.0)。同時,為了方便,最好將D:\ws-core-4.0.0\bin目錄添加到系統目錄PATH中。這樣可以方便我們執行Globus自帶的一些命令。
此外,還需要安裝Python腳本執行程序。目前最新的版本是2.4.1,可以到服務器Softwares目錄下去下載。另外,還需要正確安裝并配置Ant,它將負責生成最終的GAR文件。同時,文檔中的EXAMPLES_DIR指代例子的安裝目錄。
2 最簡單的例子
要編寫、部署這樣一個Web Service需要一下5個簡單的步驟:
l 通過編寫WSDL文件,定義服務的接口
l 通過編寫Java代碼,實現上述接口定義的服務
l 編寫WSDD部署描述符和JNDI
l 使用ant編譯并形成GAR(Globus ARchive)文件
l 通過GT4自帶的工具部署服務
下面,我們分別介紹以上五個步驟:
2.1 定義服務接口
通過編寫WSDL文件,來定義我們提供服務的接口。這樣,客戶端通過解析WSDL文件,從而了解服務的具體定義和調用情況。
2.1.1 文件代碼
具體的文件(Math.wsdl)如下:
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="MathService"
targetNamespace="http://www.globus.org/namespaces/examples/core/MathService_instance"
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" />
<!--============================================================
T Y P E S
============================================================-->
<types>
<xsd:schema targetNamespace="http://www.globus.org/namespaces/examples/core/MathService_instance"
xmlns:tns="http://www.globus.org/namespaces/examples/core/MathService_instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!-- REQUESTS AND RESPONSES -->
<xsd:element name="add" type="xsd:int"/>
<xsd:element name="addResponse">
<xsd:complexType/>
</xsd:element>
<xsd:element name="subtract" type="xsd:int"/>
<xsd:element name="subtractResponse">
<xsd:complexType/>
</xsd:element>
<xsd:element name="getValueRP">
<xsd:complexType/>
</xsd:element>
<xsd:element name="getValueRPResponse" type="xsd:int"/>
<!-- RESOURCE PROPERTIES -->
<xsd:element name="Value" type="xsd:int"/>
<xsd:element name="LastOp" type="xsd:string"/>
<xsd:element name="MathResourceProperties">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="tns:Value" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="tns:LastOp" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
<!--============================================================
M E S S A G E S
============================================================-->
<message name="AddInputMessage">
<part name="parameters" element="tns:add"/>
</message>
<message name="AddOutputMessage">
<part name="parameters" element="tns:addResponse"/>
</message>
<message name="SubtractInputMessage">
<part name="parameters" element="tns:subtract"/>
</message>
<message name="SubtractOutputMessage">
<part name="parameters" element="tns:subtractResponse"/>
</message>
<message name="GetValueRPInputMessage">
<part name="parameters" element="tns:getValueRP"/>
</message>
<message name="GetValueRPOutputMessage">
<part name="parameters" element="tns:getValueRPResponse"/>
</message>
<!--============================================================
P O R T T Y P E
============================================================-->
<portType name="MathPortType"
wsdlpp:extends="wsrpw:GetResourceProperty"
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>
<operation name="getValueRP">
<input message="tns:GetValueRPInputMessage"/>
<output message="tns:GetValueRPOutputMessage"/>
</operation>
</portType>
</definitions>
該文件被保存在EXAMPLES_DIR\schema\examples\MathService_instance目錄下。
2.1.2 名字空間的映射
通過下面文件(EXAMPLES_DIR\namespace2package.mappings)來完成WSDL中名字空間的映射:
http\://www.globus.org/namespaces/examples/core/MathService_instance=org.globus.examples.stubs.MathService_instance
http\://www.globus.org/namespaces/examples/core/MathService_instance/bindings=org.globus.examples.stubs.MathService_instance.bindings
http\://www.globus.org/namespaces/examples/core/MathService_instance/service=org.globus.examples.stubs.MathService_instance.service
2.2 實現服務
下面就實現前面接口中定義的。
2.2.1 QName接口
我們會頻繁的通過服務的Qualified Name來訪問給服務,所以將這個Qualified Name定義到一個接口(EXAMPLES_DIR \org\globus\examples\services\core\first\impl)中:
// MathQNames.java
package org.globus.examples.services.core.first.impl;
import javax.xml.namespace.QName;
public interface MathQNames {
public static final String NS = "http://www.globus.org/namespaces/examples/core/MathService_instance";
public static final QName RP_VALUE = new QName(NS, "Value");
public static final QName RP_LASTOP = new QName(NS, "LastOp");
public static final QName RESOURCE_PROPERTIES = new QName(NS,
"MathResourceProperties");
}
2.2.2 服務的實現
在這個最簡單的例子中,我們將所有的有關服務(service)和資源(resource)的代碼都放入一個類中。但是,通常情況下,會有兩個類文件。一個用來存放有關服務的代碼,一個用來存放有關資源的代碼。
類的代碼如下:
package org.globus.examples.services.core.first.impl;
import java.rmi.RemoteException;
import org.globus.wsrf.Resource;
import org.globus.wsrf.ResourceProperties;
import org.globus.wsrf.ResourceProperty;
import org.globus.wsrf.ResourcePropertySet;
import org.globus.wsrf.impl.ReflectionResourceProperty;
import org.globus.wsrf.impl.SimpleResourcePropertySet;
import org.globus.examples.stubs.MathService_instance.AddResponse;
import org.globus.examples.stubs.MathService_instance.SubtractResponse;
import org.globus.examples.stubs.MathService_instance.GetValueRP;
public class MathService implements Resource, ResourceProperties {
/* Resource Property set */
private ResourcePropertySet propSet;
/* Resource properties */
private int value;
private String lastOp;
/* Constructor. Initializes RPs */
public MathService() throws RemoteException {
/* Create RP set */
this.propSet = new SimpleResourcePropertySet(
MathQNames.RESOURCE_PROPERTIES);
/* Initialize the RP's */
try {
ResourceProperty valueRP = new ReflectionResourceProperty(
MathQNames.RP_VALUE, "Value", this);
this.propSet.add(valueRP);
setValue(0);
ResourceProperty lastOpRP = new ReflectionResourceProperty(
MathQNames.RP_LASTOP, "LastOp", this);
this.propSet.add(lastOpRP);
setLastOp("NONE");
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
/* Get/Setters for the RPs */
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public String getLastOp() {
return lastOp;
}
public void setLastOp(String lastOp) {
this.lastOp = lastOp;
}
/* Remotely-accessible operations */
public AddResponse add(int a) throws RemoteException {
value += a;
lastOp = "ADDITION";
return new AddResponse();
}
public SubtractResponse subtract(int a) throws RemoteException {
value -= a;
lastOp = "SUBTRACTION";
return new SubtractResponse();
}
public int getValueRP(GetValueRP params) throws RemoteException {
return value;
}
/* Required by interface ResourceProperties */
public ResourcePropertySet getResourcePropertySet() {
return this.propSet;
}
}
2.3 在Web服務部署描述符中配置服務
我們需要把些好的Web服務部署到Web容器中去,才能讓客戶端對服務進行訪問。這一步我們是通過Web服務部署描述符(WSDD)來實現的。
2.3.1 WSDD(Web Service Deploy Descriptor)
<?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/first/MathService" provider="Handler" use="literal" style="document">
<parameter name="className" value="org.globus.examples.services.core.first.impl.MathService"/>
<wsdlFile>share/schema/examples/MathService_instance/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"/>
<parameter name="loadOnStartup" value="true"/>
</service>
</deployment>
我們將這個文件(deploy-server.wsdd)放于EXAMPLES_DIR\ org\globus\examples\services\core\first目錄下。
2.3.2 JNDI
雖然這里面我們使用最簡單的一個例子,但是JNDI文件還是必須的,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<jndiConfig xmlns="http://wsrf.globus.org/jndi/config">
<service name="examples/core/first/MathService">
<resource name="home" type="org.globus.wsrf.impl.ServiceResourceHome">
<resourceParams>
<parameter>
<name>factory</name>
<value>org.globus.wsrf.jndi.BeanFactory</value>
</parameter>
</resourceParams>
</resource>
</service>
</jndiConfig>
2.4 創建GAR文件
在這里,我們需要Ant和Python的支持。首先,簡單的將源文件中的build.xml、build.mappings以及globus-build-service.py三個文件拷貝到EXAMPLES_DIR目錄下。在命令行上加入如下命令創建GAR文件:
globus-build-service.py first
輸出的結果像下面這樣:
Buildfile: build.xml
init:
[mkdir] Created dir: D:\test\build
[mkdir] Created dir: D:\test\build\classes
[mkdir] Created dir: D:\test\build\lib
[mkdir] Created dir: D:\test\build\stubs-org_globus_examples_services_core_f
irst
[mkdir] Created dir: D:\test\build\stubs-org_globus_examples_services_core_f
irst\src
[mkdir] Created dir: D:\test\build\stubs-org_globus_examples_services_core_f
irst\classes
[mkdir] Created dir: D:\test\build\stubs
[mkdir] Created dir: D:\test\build\stubs\classes
[mkdir] Created dir: D:\test\build\schema
[copy] Copying 30 files to D:\test\build\schema
[mkdir] Created dir: D:\test\org\globus\examples\services\core\first\etc
flatten:
WSDLUptodate:
flatten:
[echo] Processing WSDL in Math.wsdl
[java] Retrieving document at 'D:\test\build\schema\examples\MathService_in
stance\Math.wsdl'.
[java] Retrieving document at '../../wsrf/properties/WS-ResourceProperties.
wsdl', relative to 'file:/D:/test/build/schema/examples/MathService_instance/Mat
h.wsdl'.
generateBindings:
bindingUptodate:
generateBinding:
[echo] Generating bindings for Math_flattened.wsdl
stubs:
mergePackageMapping:
[echo] Merging D:\test\namespace2package.mappings
generateStubs:
[echo] Generating stubs from Math_service.wsdl
[java] {http://schemas.xmlsoap.org/ws/2004/03/addressing}Action already exi
sts
factoryFlatten:
generateFactoryBindings:
factoryStubs:
compileStubs:
[javac] Compiling 10 source files to D:\test\build\stubs-org_globus_examples
_services_core_first\classes
[copy] Copying 10 files to D:\test\build\stubs\classes
jarStubs:
[jar] Building jar: D:\test\build\lib\org_globus_examples_services_core_fi
rst_stubs.jar
compile:
[javac] Compiling 2 source files to D:\test\build\classes
jar:
[jar] Building jar: D:\test\build\lib\org_globus_examples_services_core_fi
rst.jar
dist:
makeGar:
testJars:
copyJars:
[copy] Copying 2 files to D:\test\tmp\gar\lib
testSchema:
copySchema:
[copy] Copying 4 files to D:\test\tmp\gar\schema
testEtc:
copyEtc:
[copy] Copied 1 empty directory to 1 empty directory under D:\test\tmp\gar\
etc
[antcall] Parent project doesn't contain any reference '${garshare.id}'
testShare:
copyShare:
[antcall] Parent project doesn't contain any reference '${gardocs.id}'
testDocs:
copyDocs:
[antcall] Parent project doesn't contain any reference '${garbin.id}'
testBin:
copyBin:
[copy] Copying 1 file to D:\test\tmp\gar
[copy] Warning: Could not find file D:\test\org\globus\examples\services\co
re\first\deploy-client.wsdd to copy.
[copy] Copying 1 file to D:\test\tmp\gar
[jar] Building jar: D:\test\org_globus_examples_services_core_first.gar
[delete] Deleting directory D:\test\tmp\gar
all:
BUILD SUCCESSFUL
Total time: 25 seconds
如果沒有出現錯誤,會在根目錄下面創建一個名為org_globus_examples_services_core_first.gar的文件。
2.5 部署服務到容器中去
此時,部署服務的工具是由GT4提供的。因為我們已經將%GLOBUS_LOCATION\bin目錄加入的系統路徑中去,所以我們可以在服務臺上直接輸入下面命令,就可以方便地將上面編寫的服務部署到服務器上去:
globus-deploy-gar org_globus_examples_services_core_first.gar
2.6 小結
通過以上五步,我們就開發了最簡單的一個基于GT4的Web服務。下面,我們將通過編寫簡單的例子對該服務進行測試。
3 測試
3.1 編寫客戶端程序
我們將編寫一個簡單的客戶端程序,并將其放在EXAMPLES_DIR \org\globus\examples\clients\MathService_instance\Client.java。它的全部代碼如下:
package org.globus.examples.clients.MathService_instance;
import org.apache.axis.message.addressing.Address;
import org.apache.axis.message.addressing.EndpointReferenceType;
import org.globus.examples.stubs.MathService_instance.MathPortType;
import org.globus.examples.stubs.MathService_instance.GetValueRP;
import org.globus.examples.stubs.MathService_instance.service.MathServiceAddressingLocator;
public class Client {
public static void main(String[] args) {
MathServiceAddressingLocator locator = new MathServiceAddressingLocator();
try {
String serviceURI = args[0];
// Create endpoint reference to service
EndpointReferenceType endpoint = new EndpointReferenceType();
endpoint.setAddress(new Address(serviceURI));
MathPortType math = locator.getMathPortTypePort(endpoint);
// Get PortType
//math = locator.getMathPortTypePort(endpoint);
// Perform an addition
math.add(10);
// Perform another addition
math.add(5);
// Access value
System.out.println("Current value: "
+ math.getValueRP(new GetValueRP()));
// Perform a subtraction
math.subtract(5);
// Access value
System.out.println("Current value: "
+ math.getValueRP(new GetValueRP()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.2 編譯客戶端程序
3.2.1 設置環境變量
在編譯客戶端程序之前,我們需要將GT4自帶的類庫導入到系統變量CLASSPATH下。為此,GT4給我們提供了一個批處理文件,我們只需要簡單的在GLOBUS_LACATION\etc目錄下執行如下命令即可:
3.2.2 編譯
接下來,到EXAMPLES_DIR目錄下,執行下面的命令來編譯客戶端程序:
javac -classpath ./build/stubs/classes/;%CLASSPATH% org/globus/examples/clients/MathService_instance/Client.java
注:在PDF文檔中給出的批處理命令是Unix/Linux系統下面的,需要對其進行更改才可以在Windows系統下正確執行!
3.2.3 啟動容器
最后,我們需要啟動容器。這時,最好另外開啟一個命令行窗口,再輸入如下命令:
globus-start-container –nosec
這時輸出的結果類似下面的代碼:
Starting SOAP server at: http://202.115.30.208:8080/wsrf/services/
With the following services:
[1]: http://202.115.30.208:8080/wsrf/services/Version
[2]: http://202.115.30.208:8080/wsrf/services/NotificationConsumerService
[3]: http://202.115.30.208:8080/wsrf/services/NotificationTestService
[4]: http://202.115.30.208:8080/wsrf/services/SecureCounterService
[5]: http://202.115.30.208:8080/wsrf/services/PersistenceTestSubscriptionManager
[6]: http://202.115.30.208:8080/wsrf/services/gsi/AuthenticationService
[7]: http://202.115.30.208:8080/wsrf/services/TestRPCService
[8]: http://202.115.30.208:8080/wsrf/services/SubscriptionManagerService
[9]: http://202.115.30.208:8080/wsrf/services/ManagementService
[10]: http://202.115.30.208:8080/wsrf/services/TestServiceWrongWSDL
[11]: http://202.115.30.208:8080/wsrf/services/WidgetService
[12]: http://202.115.30.208:8080/wsrf/services/SampleAuthzService
[13]: http://202.115.30.208:8080/wsrf/services/examples/core/first/MathService
[14]: http://202.115.30.208:8080/wsrf/services/AuthzCalloutTestService
[15]: http://202.115.30.208:8080/wsrf/services/WidgetNotificationService
[16]: http://202.115.30.208:8080/wsrf/services/AdminService
[17]: http://202.115.30.208:8080/wsrf/services/ShutdownService
[18]: http://202.115.30.208:8080/wsrf/services/ContainerRegistryService
[19]: http://202.115.30.208:8080/wsrf/services/CounterService
[20]: http://202.115.30.208:8080/wsrf/services/TestService
[21]: http://202.115.30.208:8080/wsrf/services/TestAuthzService
[22]: http://202.115.30.208:8080/wsrf/services/SecurityTestService
[23]: http://202.115.30.208:8080/wsrf/services/ContainerRegistryEntryService
[24]: http://202.115.30.208:8080/wsrf/services/NotificationConsumerFactoryServic
e
[25]: http://202.115.30.208:8080/wsrf/services/TestServiceRequest
這時,注意觀察,我們剛才部署的服務是否正常啟動。
注:默認容器需要占用8080端口,如果系統上安裝了Tomcat這樣應用服務器,也有可能也占用了該端口。所以可以將Tomcat服務暫時關閉。
3.3 測試結果
如果發現了類似上面紅色代碼那段,表示容器中已經成功啟動了我們發布的服務。此時,在原先的那個命令行下輸入如下命令來執行我們寫的客戶端程序:
java -classpath ./build/stubs/classes/;%CLASSPATH% org.globus.examples.clients.MathService_instance.Client http://127.0.0.1:8080/wsrf/services/examples/core/first/MathService
注:在PDF文檔中給出的批處理命令是Unix/Linux系統下面的,需要對其進行更改才可以在Windows系統下正確執行!
如果我們連續執行兩次上面的命令,會輸出如下結果:
D:\test>java -classpath ./build/stubs/classes/;%CLASSPATH% org.globus.examples.c
lients.MathService_instance.Client http://127.0.0.1:8080/wsrf/services/examples/
core/first/MathService
Current value: 15
Current value: 10
D:\test>java -classpath ./build/stubs/classes/;%CLASSPATH% org.globus.examples.c
lients.MathService_instance.Client http://127.0.0.1:8080/wsrf/services/examples/
core/first/MathService
Current value: 25
Current value: 20
3.4 小結
通過上面的測試,我們可以驗證Web服務的正確性。同時要注意Windows和Unix/Linxu系統下命令書寫的差別。
來自:http://www.tkk7.com/sk8boy/archive/2006/12/15/14573.html