随笔-49  评论-67  文章-27  trackbacks-0

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编译并形成GARGlobus 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 WSDDWeb 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文件

在这里,我们需要AntPython的支持。首先,简单的将源文件中的build.xmlbuild.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 小结

通过以上五步,我们就开发了最简单的一个基于GT4Web服务。下面,我们将通过编写简单的例子对该服务进行测试。

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目录下,执行下面的命令来编译客户端程序:

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服务的正确性。同时要注意WindowsUnix/Linxu系统下命令书写的差别。

posted on 2005-10-01 09:36 思考 阅读(1503) 评论(1)  编辑  收藏 所属分类: Grid Computing

评论:
# re: GT4编程 First Step 2006-12-15 23:35 | sky[匿名]
我会试试的。
很感谢!  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: