liaowz

BlogJava 首页 新随笔 联系 聚合 管理
  3 Posts :: 0 Stories :: 1 Comments :: 0 Trackbacks

2006年4月10日 #

用Globus Toolkit 4构建WEB服务

xzzhouhu 发表于 2005-12-06
点击数:1041 评论数:0 评价:3/1
关键词:Globus Toolkit

摘要:

本文主要介绍了通过一种新的方法来构建企业软件,即通过调整Globus Toolkit 4实现的网格计算的概念来实现。GT4是一种可以通过开放网格服务架构(OGSI)来实施的开放资源。这种实施主要目的是为网格服务架构提供了依据,同时也可以为别的网格服务架构实施提供参考。本文详细介绍了GT4中JAVA的核心服务,这些服务具备提供代管网格服务实时运行环境的能力,当然这些网格服务都是由JAVA写的。实时运行环境在网格服务的应用和网络承载之间和传输协议引擎之间起到了协调的作用。

文章工具


用Globus Toolkit 4(GT4)构建WEB服务

作者:Birali Hakizumwami

译者:xzzhouhu






版权声明:任何获得Matrix授权的网站,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明
作者:Birali Hakizumwami;xzzhouhu
原文地址:http://www.onjava.com/pub/a/onjava/2005/10/19/constructing-web-services-with-globus-toolkit.html
中文地址:http://www.matrix.org.cn/resource/article/44/44032_Globus_Toolkit.html
关键词: Globus Toolkit

摘要:
本文主要介绍了通过一种新的方法来构建企业软件,即通过调整Globus Toolkit 4实现的网格计算的概念来实现。GT4是一种可以通过开放网格服务架构(OGSI)来实施的开放资源。这种实施主要目的是为网格服务架构提供了依据,同时也可以为别的网格服务架构实施提供参考。本文详细介绍了GT4中JAVA的核心服务,这些服务具备提供代管网格服务实时运行环境的能力,当然这些网格服务都是由JAVA写的。实时运行环境在网格服务的应用和网络承载之间和传输协议引擎之间起到了协调的作用。


一.网格的定义

网格的定义:
网格就是将收集网络上所有可用的分布式计算资源提供给最终用户或组建成一个巨大的计算系统。网格计算给分布式计算提供了一种全新的方法,不仅在跨地区而且在跨组织,机器结构和软件限制,给连接到网格的每个用户提供更多的资源,计算机之间的协作和信息访问。分布式资源,像计算周期,存储和信息,可以在网格中的任何地区访问,同时也可以在网格中提供这些服务供其他用户访问。这就要通过在每个独立的组织或资源之间进行安全的协调资源共享,共同建立一个动态虚拟组织机构。


二.Globus Toolkit Version 4

在本文中,我们主要讨论GT4中JAVA的核心服务。(如图1),这些服裉峁┝舜芡穹袷凳痹诵谢肪车哪芰ΑJ凳痹诵谢肪吃谟没Фㄒ宓挠τ梅窈虶T4的核心服务之间,网络承载和传输协议引擎之间起到了协调的作用。GT4核心服务还提供了程序开发支持的功能,包括开放式开发模式和访问网格服务的实现,像GRAM(Grid Resource Allocation Management,网格资源管理)。应用GT4强有力的理由就是因为它是建立在现有的WEB服务标准和技术的基础上,像SOAP和WSDL。网格服务提供的接口都是通过WSDL来描述的。GT4提供了一个软件仓库,像安全支持,软件的探索,软件的资源管理,软件的调用,软件之间的通信,异常处理和数据管理等。

image
                   (图1)

图1主要描述了在服务器端的GT4中的主要组件结构。这只是GT4所提供功能的一部分,我们只是认为它很适合本文。GT4结构由一个网格容器组成,网格容器主要用来管理所有部署的WEB服务,贯穿于每个WEB服务的运行周期。GT4使用apache的axis作为它的WEB服务的引擎来处理所有的SOAP消息,JAX-RPC (Java API for XML-Based RPC)处理和WEB服务的配置。


三.贷款偿还例子:

我们列举这样一个例子,主要想向大家展示在企业内部如何通过Globus Toolkit 来解决不同类操作系统之间进行融合。在企业内部,有些应用可能是原来主机遗留下来的,技术比较落后,有些应用已经采用了现代技术,像J2EE。甚至我们采用最先进的技术在一个企业内部的应用之间进行信息共享也要面临巨大的挑战。图2给出了这样一个例子,在一个抵押机构内,在贷款偿还信息处理和会计部门信息处理之间的交互,

image
                (图2)

会计部门使用申请贷款处理服务来申请贷款。

为了创建和部署网格服务,我们需要:
*通过创建WSDL文件来定义服务的接口
*用JAVA来实现
*通过创建WSDD文件来定义服务的部署参数
*使用ANT编译源代码并生成GAR文件
*用GT4分发工具部署GAR文件
我们必须使用从上往下的方法来创建网格服务,(图3)

这种方法首先从提供WSDL文件开始,在WSDL文件中包括对WEB服务的抽象定义,包括服务类型,消息类型和端口类型。从WSDL文档开始并根据WSDL文档创建了JAVA模型,从而导致与其他系统更好交互。

image

  我们使用GT4 toolkit自带的工具来进行服务的绑定和产生客户段需要的根类。这种方法的下一步就是提供接口的实现。

贷款偿还服务处理定义:
对于贷款偿还服务处理的例子的接口类型我们定义为loan.wsdl,它描述了贷款偿还服务所提供的三个部分的操作(申请贷款,贷款处理和获得贷款)。首先我们描述贷款偿还服务的请求和响应:

<types>

  <xsd:element name="createLoan">
    <xsd:complexType>
      <xsd:sequence>
          <xsd:element name="loanNumber" type="xsd:int"/>
        <xsd:element name="amountUPB" type="xsd:double"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="createLoanResponse">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="returnValue" type="xsd:int"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="processLoanPayment">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="loanNumber" type="xsd:int"/>
        <xsd:element name="amount" type="xsd:double"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="processLoanPaymentResponse">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="returnValue" type="xsd:int"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="getLoan">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="loanNumber" type="xsd:int"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="getLoanResponse">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="returnValue" type="tns:LoanType"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>

</types>


我们在文件 loan.xsd.中定义了贷款的数据类型,我们通过使用“ import <xsd:import schemaLocation="loan.xsd"/> ”可以直接将loan.xsd.文件导入到文件loan.wsdl 中,并且用它作为获得贷款操作返回的类型

<complexType name="LoanType">
    <sequence>
        <element name="loanNumber" type="int"/>
        <element name="UPB" type="double"/>
        <element name="status" type="string"/>
        <element name="createDate" type="string"/>
    </sequence>
</complexType>


下一步,我们要定义所有的消息服务。一条消息元素可能由一个或多个部分组成,消息元素的每个部分对应一个参数,并且还有一个类型属性。消息既可以是一个请求消息(输入消息),也可以是一个响应消息(输出消息)。

<message name="CreateLoanInputMessage">
  <part name="parameters" element="tns:createLoan"/>
</message>
<message name="CreateLoanOutputMessage">
  <part name="parameters" element="tns:createLoanResponse"/>
</message>

<message name="ProcessLoanPaymentInputMessage">
  <part name="parameters" element="tns:processLoanPayment"/>
</message>
<message name="ProcessLoanPaymentOutputMessage">
  <part name="parameters"
    element="tns:processLoanPaymentResponse"/>
</message>

<message name="GetLoanInputMessage">
  <part name="parameters" element="tns:getLoan"/>
</message>
<message name="GetLoanOutputMessage">
  <part name="parameters" element="tns:getLoanResponse"/>
</message>


最后我们定义所有的端口类型,每个接口类型定义了一个或多个操作来使用当前的操作元素,每个独立的操作元素又定义了一个操作和与操作有联系的消息的输入输出。在一个端口类型内操作元素定义了端口类型内所有调用方法的语法。

<portType name="LoanPortType">
  <operation name="createLoan">
    <input message="tns:CreateLoanInputMessage"/>
    <output message="tns:CreateLoanOutputMessage"/>
    <fault name="Fault" message="ogsi:FaultMessage"/>
  </operation>
  <operation name="processLoanPayment">
    <input message="tns:ProcessLoanPaymentInputMessage"/>
    <output message="tns:ProcessLoanPaymentOutputMessage"/>
    <fault name="Fault" message="ogsi:FaultMessage"/>
  </operation>
  <operation name="getLoan">
    <input message="tns:GetLoanInputMessage"/>
    <output message="tns:GetLoanOutputMessage"/>
    <fault name="Fault" message="ogsi:FaultMessage"/>
  </operation>
</portType>


服务的实现:
  在前面的步骤中,终端贷款端口类型的接口已经产生,在定义这些端口类型的接口时,所有的远程操作都要设为public,并且抛出java.rmi.RemoteException。在本文中给出了LoanServiceImpl类,主要实现贷款端口类型的接口,这些实现要用到前面所讲到的用loan.wsdl文件所生成的根类。

public class LoanServiceImpl implements LoanPortType


其中LoanServiceImpl 所实现的方法定义在LoanPortType接口中,createLoan方法在产生一个createLoan对象的构造器中要获取一个贷款数字作为它的参数。

public CreateLoanResponse createLoan(CreateLoan cl)
throws java.rmi.RemoteException
public ProcessLoanPaymentResponse processLoanPayment(ProcessLoanPayment plp)
throws java.rmi.RemoteException
public GetLoanResponse getLoan(GetLoan gl) throws java.rmi.RemoteException


请参考完整代码详细描述方法的实现。

编译并创建贷款/偿还处理的WEB服务:
下面我们介绍通过以下步骤来创建易部署的GT4打包文档。Ant在编译本文所提供文件时所产生的build.xml中包含了ant的执行任务的步骤。在build.xml中ant的执行任务调用GT4中的ant任务,这些任务伴随着GT4的发布可以在编译文件中找到。

%GLOBUS_LOCATION%/share/globus_wsrf_common/build-packages.xml
%GLOBUS_LOCATION%/share/globus_wsrf_tools/build-stubs.xml
%GLOBUS_LOCATION%/share/schema


编译GT4中易部署的GAR文件
   为了创建易部署的网格打包文件,loan.gar,我们通过以下步骤来实现:(这些步骤与builder.xml中的ant任务是一致的):
·        与WSDL文件绑定
·        通过WSDL        文件生成一个根类,在安装时,提供一个特殊文件来对不同的命名空间和包之间进行映射,这些包与表格中的目录结构一致。
·        编译根类
·        编译接口类
·        用JAR压缩接口类,和根类一样(loan.jar and loan_stubs.jar).
·        通过创建部署描述文件deploy-server.wsdd.来生成易部署的GAR文件,loan.gar
请参考源代码中完整的build.xml文件,通过以上步骤来实现一系列的ant编译任务。GT4描述我们的WEB服务文件deploy-server.wsdd就想这样:

<service name="loan/impl/LoanService" provider="Handler"
use="literal" style="document">
    <parameter name="className" value="loan.impl.LoanServiceImpl"/>
    <wsdlFile>share/schema/loan/Loan_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>


让我们来介绍一下deploy-server.wsdd中的一些参数:
服务名称:指定我们所提供的WEB服务的路径,我们将它与WEB服务容器的地址相结合起来,我们会得到WEB服务的完整的URL。为了便于测试,使用独立的GT4容器,URL就像这样:

http://localhost:8080/wsrf/services/loan/impl/LoanService

类名:指实现服务接口的类(LoanServiceImpl).
WSDL文件:告诉GT4中的WEB服务容器对于当前的WEB服务的WSDL文件在那里可以找到。WSDL文件Loan_service.wsdl是在GT4 从loan.wsdl进行ANT时自动产生的。
启动时装载:如果我们需要服务在WEB服务容器启动时就开始装载,允许我们控制服务的装载。

部署GAR文件:
GAR文件loan.gar包含了所有的文件和WEB服务器需要的部署信息,我们使用GT4部署工具:

%GLOBUS_LOCATION%/bin/globus-deploy-gar $PROJECT_HOME/loan.gar

拷贝文档文件(loan.wsdl,编译的根类,编译的接口实现,loan.wsdd)到GT4容器的目录下适当位置。

测试借贷款处理实例

在图1描述了如何将贷款方的子系统和贷款结算子系统作为借贷款的WEB服务的客户端,现在我们就在GT4网格服务容器中创建和部署WEB服务,我们需要用一个客户端进行测试,测试用例模拟一个贷款事件,一个贷款月度偿还事件和一个贷款还清事件。作为客户端来说,他们希望WEB服务的URI(统一资源标识符)能够作为客户端访问WEB服务的依据。客户端的程序要独立的进行编译,下面来描述客户端访问WEB服务的主要步骤:

创建一终端引用类型对象,来代表终端引用的贷款服务。我们的终端引用只需要服务的URI:
EndpointReferenceType endpoint = new EndpointReferenceType();
endpoint.setAddress(new Address(serviceURI));

下一步,我们要获得引用服务的端口类型,这需要一个根类调用LoanServiceAddressingLocator, LoanServiceAddressingLocator主要是用来维持客户端与WEB服务之间的通信和获得引用贷款端口的类型。
LoanServiceAddressingLocator locator = new LoanServiceAddressingLocator();
LoanPortType loanPT = locator.getLoanPortTypePort(endpoint);


一旦我们获得这个引用,我们可以作为本地对象来操作WEB服务。例如,调用远程的创建操作,我们仅仅需要在贷款端口类型中使用创建方法。
CreateLoanResponse clr = loanPT.createLoan(new CreateLoan(amount, loanNumber));

请参考附件中完整的客户端代码。在编译客户端之前,请保证运行下面的脚本,以便于GT4的发布:
%GLOBUS_LOCATION%/etc/globus-devel-env.bat

globus-devel-env.bat文件主要是将Globus的类库注册到系统的classpath中,因为客户端是作为独立的应用来编译的,同样,要保证在编译客户端的目录中所放置的已编译的根类时能通过classpath找到,因此我们的客户端可以访问服务器端的根类,像LoanServiceAddressingLocator。

启动网格容器
使用下面的命令来启动网格容器:

%GLOBUS_LOCATION%/bin/globus-start-container –nosec

-nosec参数主要是为了简化测试,略去安全设置。如果网格容器启动成功,你将会看到已部署的服务的URI列表,如果LoanService正确的部署,在已部署的服务的列表中有下面的一行:

[13]: http://localhost:8080/wsrf/services/loan/impl/LoanService

测试借贷款处理的WEB服务
通过客户端进行测试,我们假设有以下操作:申请贷款,偿还贷款,还清贷款。

·        创建一个初始化贷款编号为100并且还有12000未还        
java Client http://172.24.15.29:8080/wsrf/services/loan/impl/LoanService createLoan 100 120000
Loan 100 created successfully.


·        假定两个月偿还,每个月还$1100(本例不考虑利息的计算)
java Client http://172.24.15.29:8080/wsrf/services/loan/impl/LoanService processLoanPayment 100 1100
Loan 100 processed successfully.
java Client http://172.24.15.29:8080/wsrf/services/loan/impl/LoanService processLoanPayment 100 1100
Loan 100 processed successfully.


·        查看贷款的状态
java Client http://172.24.15.29:8080/wsrf/services/loan/impl/LoanService getLoanData 100
Loan Data
Create Date Mon Jun 06 16:41:06 EDT 2005
Unpaid Principal Balance 117800.0
Status ACTIVE


·        第三个月还清余款($117,800)
java Client http://172.24.15.29:8080/wsrf/services/loan/impl/LoanService processLoanPayment 100 117800
Loan 100 processed successfully


·        查看贷款状态
java Client http://172.24.15.29:8080/wsrf/services/loan/impl/LoanService getLoanData 100
Loan Data
Create Date Mon Jun 06 16:41:06 EDT 2005
Unpaid Principal Balance 0.0
Status PAIDOFF


结束语:

本文主要描述了在基于现有的WEB服务标准的基础上,如何调整GT4网格结构来创建一个网格服务应用。尽管GT4已经主要的应用在大型的科学计算问题上,但是在一个企业内部它可以作为实现面向服务结构(SOA)的一种方法。本文主要是通过一个简单的实例来描述如何使用GT4中的JAVA核心服务来创建和部署一个网格服务,但是并没有覆盖到更多的其他的更先进的关于如何使用网格服务概念,向网格服务的分配和管理,文件传输的可靠性,网格异常和安全。

资源
·本文的示例代码
·Matrix-Java开发者社区:http://www.matrix.org.cn
·onjava.com:onjava.com
posted @ 2006-04-19 13:13 wenzhao 阅读(210) | 评论 (0)编辑 收藏

一:说明
Digester是jakarta commons里面的一个包,最早运用于Struts中xml文件的解析.后来独立出来
归到commons下面.主要的开发人员是:Craig McClanahan。Craig McClanahan是我比较崇拜的开发
人员之一。他开发了无数的OpenSource项目。包括大家都知道的Tomcat、Struts同时还是jsp,servlet
Spec制定成员之一,并是Java Server Face(jsf)的Team Leader.在此向Craig McClanahan致敬。
Digester把xml文件解析为Java Object有点象Castor。在本文中我使用一个简单的例子来介绍
Digester的使用,详细的文档看下面的连接:http://jakarta.apache.org/commons/digester.html
我做一个最简单的例子,因为Digester功能比较强大,需要更详细的例子参阅下面的文章
http://www.onjava.com/pub/a/onjava/2002/10/23/digester.html?page=1
http://www.javaworld.com/javaworld/jw-10-2002/jw-1025-opensourceprofile.html
使用Digester,需要jakarta下的如下包: BeanUtils, Collections, Logging.
Digester的下载地址:
http://apache.linuxforum.net/dist/jakarta/commons/digester/binaries/
目前版本为1.4

二:开始使用Digester.
现在有一个如下的xml文件
user.xml(e:/user.xml)
-------
<users>
<name>BASIC</name>
<pass>Example Basic Authentication Area</pass>
</users>

一个如下的java Object
com.henry.test.digester.BaseObject
-----------------------------------
public class BaseObject {
private String name = "";
private String pass = "";
/**
* Returns the name.
* @return String
*/
public String getName() {
return name;
}

/**
* Returns the pass.
* @return String
*/
public String getPass() {
return pass;
}

/**
* Sets the name.
* @param name The name to set
*/
public void setName(String name) {
this.name = name;
}

/**
* Sets the pass.
* @param pass The pass to set
*/
public void setPass(String pass) {
this.pass = pass;
}

public void setInfo(String name,String pass){
this.name = name;
this.pass = pass;

}

public void info() {
log("name:" + name + "...pass :" + pass);
}

private void log(String str) {
System.out.println(str);
}
}
现在我们要把user.xml里面的内容解析为一个BaseObject.
在以前我使用JDOM做解析。代码估计需要100行左右。
现在我使用Digester完成此项工作,你会发现非常的容易,而且很简单。

三:解析xml文件
Test.java
---------------
//import org.apache.commons.digester.Digester;
...............

public void parse() {
Digester digester = new Digester();
//创建Digester对象
BaseObject obj = new BaseObject();
try {
digester.addObjectCreate("users", "com.henry.test.digester.BaseObject");
//创建一个对象com.henry.test.digester.BaseObject
//对象对应的xml中为容users下的配置
digester.addCallMethod("users/name", "setName", 0);
//调用对象的方法setName并把users/name节点的值作为对象方法的参数
digester.addCallMethod("users/pass", "setPass", 0);
/*下面是调用setInfo(String,String)设置信息的使用
*digester.addObjectCreate("users", "com.henry.test.digester.BaseObject");
*digester.addCallMethod("users","setInfo",2);
*digester.addCallParam("users/name",0);
*digester.addCallParam("users/pass",1);
*/
//上面的两段代码功能一样都是使用反射实现对象的创建和方法的调用
//第二段是一个方法有多个参数的情况
obj=(BaseObject)(digester.parse("e:/user.xml"));
obj.info();
} catch (Exception ex) {
log(ex.getMessage());
}
}
............

上面的如此简单的代码就可以实现一个配置文件的解析。不错吧。

四:结束语
xml解析的方式有很多种,简单的运用jdom就可以解决问题.再不行使用Xerces等等。但对于一些
配置文件的解析使用Digester不失为一个很好的选择.简单,而且基本可以满足需要。够用为原则.
我没有去比较使用Digester,jdom的运行效率,因为实在是没有必要。但我使用过jdom去解析,虽然
很简单,但肯定比Digester复杂.
如果你对Digester有更深的理解,记得联系我:henry_ge@mail.com.如果上面的文章有什么错误
或者不足,也请给我指出,发送到上面的地址.

    
 

posted @ 2006-04-10 09:19 wenzhao 阅读(346) | 评论 (0)编辑 收藏