GT4編程實例

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

將以上代碼放入namespace2package.mappings文件,在放入指定文件夾

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

如果沒有出現錯誤,會在根目錄下面創建一個名爲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目錄下執行如下命令即可:

globus-devel-setcp.bat

3.2.2 編譯

接下來,到EXAMPLES_DIR目錄下,執行下面的命令來編譯客戶端程序:
set classpath=./build/stubs/classes/;%CLASSPATH%
javac org\globus\examples\clients\MathService_instance\Client.java

注:在PDF文檔中給出的批處理命令是Unix/Linux系統下面的,需要對其進行更改纔可以在Windows系統下正確執行!

3.2.3 啓動容器

最後,我們需要啓動容器。這時,最好另外開啓一個命令行窗口,再輸入如下命令:

globus-start-container –nosec
注:默認容器需要佔用8080端口,如果系統上安裝了Tomcat這樣應用服務器,也有可能也佔用了該端口。所以可以將Tomcat服務暫時關閉。

3.3 測試結果

如果發現容器中多了一個自己的web service那就說明添加成功了
此時,在原先的那個命令行下輸入如下命令來執行我們寫的客戶端程序:

java  org.globus.examples.clients.MathService_instance.Client               http://127.0.0.1:8080/wsrf/services/examples/core/first/MathService

如果我們連續執行兩次上面的命令,會輸出如下結果:

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系統下命令書寫的差別

此鏈接爲源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章