Apache Tuscany SCA入门

来源:互联网 发布:淘宝不能发布护肤品 编辑:程序博客网 时间:2024/05/10 08:25
 

SCA导航1-Apache Tuscany SCA入门

分类: SOA2009-04-29 16:38 1123人阅读 评论(0) 收藏 举报

目录(?)[+]

本文根据Apache Tuscany 1.x文档翻译编写

1.   Build Calculator Using Command Line

1.1. 前言

这篇导航文章使用基于命令行的方式开始Apache Tuscany Java SCA。Tuscany提供了许多样例,其中最简单之一的就是计算器样例(The Calculator Sample)。我们将使用此样例,所以请确保已经正确下载Tuscany。正如此样例名称暗示,此样例是个典型的计算操作。给定二个数,然后将操作作用于它们。我们将处理加(add),减(subtract),乘(multiply),除(divide)等操作。看完这篇导航后你将知道如果开发,部署,运行计算器样例,并且知道怎么配置使之运行于不同环境。

1.2. 安装环境

首先我们将运行计算器样例以确保已正确安装了Tuscany,然后将介绍如何一步步地实现计算器样例,这样你就可以知道如何开发单独运行于SCA环境的Apache Tuscany Java SCA基本应用。接下来我们将更新计算器样例,以介绍Apache Tuscany Java SCA的其他JAVA拓展。最后我们将用计算器样例展示如何构建使用Apache Tuscany Java SCA的面向服务架构(Service Oriented Architecture,SOA)的分布式应用。

l         下载Apache Tuscany Java SCA

下载界面分别有Windows,Linux上的二进制,源码版本。这边下载二进制版本即可。

l         下载JDK

若没有安装JDK,必须先安装,版本需是1.5或之后的版本。

l         下载构建工具

构建工具可以使用Maven 2.0.7+,或Ant 1.7.0+。

1.3. 运行存在的计算器应用

Tuscany Java SCA的二进制版本中提供了一个计算器应用,你可以从samples/calculator目录找到。如图-1所示每个样例都有个README文件,里面说明了如何运行该样例,及一个PNG图片展示SCA应用样子。

图-1

我们先来运行此样例,以有个感性认识。运行此例很简单,只需从命令行中切换到samples/calculator目录执行如下命令

>ant run

若没有安装ant,可以按如下命令运行

Windows

>java  -cp../../lib/tuscany-sca-manifest.jar;target/sample-calculator.jar calculator.CalculatorClient  

Linux

>java  -cp../../lib/tuscany-sca-manifest.jar:target/sample-calculator.jar calculator.CalculatorClient  

运行结果如下

3 + 2=5.0

3 - 2=1.0

3 * 2=6.0

3 / 2=1.5

 

1.4. 用JAVA构建计算器应用

这个样例展示如何定义你的应用,使之关注于业务逻辑。它将引导你一步步构建计算器应用,这个组合构件(Composite)里的所有构件(Component)都是本地且用JAVA接口描述的。

1.4.1.    定义构建应用所需的模块(Block)

想想如何将你的应用分解成更小的功能或服务。每个模块是一个能够在整个应用使用的逻辑单元。在这个样例中,计算器应用可以分解成5个模块:AddService模块,SubtractService模块,MultiplyService模块,DivideService模块及一个接收并路由请求到相应模块的主入口模块,我们把这个主模块称作CalculatorService。

图-2

1.4.2.    实现每个模块

现在你已经分解出你的应用中的每个功能模块,准备实现这些模块。在SCA中功能模块被抽象为构件(Component),所以看看我们是怎么实现这些构件的。我们使用AddService构件作为第一个例子。

AddService构件提供将二个实数相加并返回操作结果的功能,当请求是加操作时,CalculatorService构件使用AddService构件。假设我们使用普通JAVA对象(POJO)写AddService构件,我们将从JAVA接口描述开始。

package calculator;

 

/**

 * The Add service interface

 */

public interface AddService {

 

    double add(double n1, double n2);

 

}

接下来提供该接口的实现

package calculator;

 

import java.util.logging.Level;

import java.util.logging.Logger;

 

/**

 * An implementation of the Add service

 */

public class AddServiceImpl implements AddService {

 

    public double add(double n1, double n2) {

        Logger logger = Logger.getLogger("calculator");

        logger.log(Level.FINEST, "Adding " + n1 + " and " + n2);

        return n1 + n2;

    }

 

}

哇,这就写了个SCA构件么?它不应该比普通JAVA接口及实现复杂么?嗯,这就是SCA构件,使用普通JAVA接口及实现就可以写出个SCA构件,SCA构件就是这么简单。我们可以不改变AddService构件实现就可以将它暴露为SCA支持的绑定形式,如Web Service,JMS,或者RMI。

让我们来看下CalculatorService构件,它引用AddService构件。

首先还是定义构件接口,它定义了CalculatorService构件提供的服务。

package calculator;

 

 

/**

 * The Calculator service interface.

 */

public interface CalculatorService {

 

    double add(double n1, double n2);

 

    double subtract(double n1, double n2);

 

    double multiply(double n1, double n2);

 

    double divide(double n1, double n2);

 

}

接着实现它

package calculator;

 

import org.osoa.sca.annotations.Reference;

 

 

/**

 * An implementation of the Calculator service.

 */

public class CalculatorServiceImpl implements CalculatorService {

 

    private AddService addService;

    private SubtractService subtractService;

    private MultiplyService multiplyService;

    private DivideService divideService;

 

    @Reference

    public void setAddService(AddService addService) {

        this.addService = addService;

    }

 

    @Reference

    public void setSubtractService(SubtractService subtractService) {

        this.subtractService = subtractService;

    }

 

    @Reference

    public void setDivideService(DivideService divideService) {

        this.divideService = divideService;

    }

 

    @Reference

    public void setMultiplyService(MultiplyService multiplyService) {

        this.multiplyService = multiplyService;

    }

 

    public double add(double n1, double n2) {

        return addService.add(n1, n2);

    }

 

    public double subtract(double n1, double n2) {

        return subtractService.subtract(n1, n2);

    }

 

    public double multiply(double n1, double n2) {

        return multiplyService.multiply(n1, n2);

    }

 

    public double divide(double n1, double n2) {

        return divideService.divide(n1, n2);

    }

 

}

我们现在有了些用JAVA实现的构件,每个构件都定义了接口,本例是使用JAVA接口。注意它们只是有业务逻辑的普通的JAVA服务。

图-3

1.5. 组装计算器应用

到目前为止,我们已经创建了几个构件。我们如何实际运行这个应用呢?JAVA程序员可能会想到用下面的方法

public class CalculatorClient {

    public static void main(String[] args) throws Exception {

 

        CalculatorServiceImpl calculatorService = new CalculatorServiceImpl();

        AddService            addService        = new AddServiceImpl();

        calculatorService.setAddService(addService);

     

        System.out.println("3 + 2=" + calculatorService.add(3, 2));

        // calls to other methods go here if we have implemented SubtractService, MultiplyService, DivideService

    }

}

但是这样没有用于Tuscany运行环境,也没有使用Web Service的接口的方式。我们来看下使用Tuscany运行环境的代码

public class CalculatorClient {

    public static void main(String[] args) throws Exception {

 

        SCADomain scaDomain = SCADomain.newInstance("Calculator.composite");

        CalculatorService calculatorService = scaDomain.getService(CalculatorService.class, "CalculatorServiceComponent");

 

        System.out.println("3 + 2=" + calculatorService.add(3, 2));

        // calls to other methods go here if we have implemented SubtractService, MultiplyService, DivideService

 

        scaDomain.close();

    }

}

你可以看到我们使用SCADomain的静态方法创建了一个SCADomain实例,SCADomain代表SCA系统的边界。它可以分布到多个处理程序,这个例子只是运行在单一的JVM环境。

参数“Calculator.composite”是一个用于描述SCA如何组装构件的XML文件。

<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"

           name="Calculator">

 

    <component name="CalculatorServiceComponent">

       <implementation.java class="calculator.CalculatorServiceImpl"/>

        <reference name="addService" target="AddServiceComponent" />

        <!-- You can add references to SubtractComponent, MultiplyComponent and DivideComponent  -->

    </component>

 

    <component name="AddServiceComponent">

        <implementation.java class="calculator.AddServiceImpl"/>

    </component>

 

    <!-- definitions of SubtractComponent, MultiplyComponent and DivideComponent -->

 

</composite>

在此文件中我们定义了二个构件,Tuscany SCA需要加载使它们在.composite文件中运行。

请注意CalculatorServiceComponent构件有一个名称为“addService”的引用,此引用名“addService”并不是巧合,而是跟CalculatorService接口的实现CalculatorServiceImpl的addService属性名称一致的。Tuscany SCA运行时解析XML composite文件中的信息,然后用这些信息创建对象及组织它们间的关系。在我们的计算器应用中,它首先会创建AddServiceImpl及CalculatorServiceImpl实例,然后将AddServiceImpl实例引用注入到CalculatorServiceImpl实例的addService属性中。仔细观察CalculatorServiceImpl的代码,可以注意到setAddService方法上的@Reference注释,这个注释告诉Tuscany SCA这个属性需要自动注入。它等价于下面的代码

CalculatorServiceImpl calculatorService = new CalculatorServiceImpl();

AddService            addService        = new AddServiceImpl();

calculatorService.setAddService(addService);

一旦composite文件被加载到SCADomain,客户端就可以通过SCADomain获取CalculatorServiceComponent构件的引用

CalculatorService calculatorService = scaDomain.getService(CalculatorService.class, "CalculatorServiceComponent");

SCA规范经常使用图表来描述SCA应用。它帮助我们快速概述应用中的构件及构件的连接方式。如果我们为计算器应用画图,它应该像图-4所示

图-4

你可以发现Tuscany中的所有样例都有提供PNG图,它使我们快速熟悉样例中的构件。

1.6. 部署计算器应用

组合构件描述SCA构件如何被实现以及它们如何通过引用到目标间的连线被装配。组合构件文件由一些依赖组成,如计算器应用依赖用于实现SCA构件定义的Java类及接口文件。组合构件文件及运行SCA应用所需的其他元素的集合组成一个或几个SCA Contribution。一个SCA Contribution可以是一文件目录,或者是一打包好的文件,如Jar文件。SCA没有要求Contribution任何特别的打包模式。在我们的这个计算器应用中,你可以把Contribution看成持有Calculator组合构件及其所有依赖。实际上你可以查看CalcalatorService应用生成的Jar包,其文件内容如下

calculator/AddService.class

calculator/AddServiceImpl.class

calculator/CalculatorClient.class

calculator/CalculatorService.class

calculator/CalculatorServiceImpl.class

calculator/DivideService.class

calculator/DivideServiceImpl.class

calculator/MultiplyService.class

calculator/MultiplyServiceImpl.class

calculator/SubtractService.class

calculator/SubtractServiceImpl.class

Calculator.composite

都是运行计算器应用所需的元素。我们只需要将此Contribution添加到SCA运行环境,然后就可以调用其提供的服务。

Tuscany所有样例都提供了build.xml及pom.xml文件,以供修改后重新构建应用。

1.7. 重新配置计算器应用-改变绑定方式

往回看,我们刚开始写的使用SCA运行时环境的计算器应用的客户端代码不比一般Java应用客户端长。我们有描述应用如何装配的XML composite文件。

对于我们的应用来说装配思想是个很大的优势,因为更加灵活且我们可以使用SCA应用编程模型改变,重用,及与其他应用整合或者后继开发。不管用什么语言实现它们。

例如,假设我们的计算器应用功能很强大又流行,我们想在公司内部共享这个应用,其他同事只要通过基于Web2.0应用的浏览器就可以访问。在Tuscany SCA中我们很容易实现,只需更改XML配置文件即可。下面展示了所需更改

<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"

           name="Calculator">

 

     <service name="CalculatorService" promote="CalculatorServiceComponent/CalculatorService">

         <interface.java interface="calculator.CalculatorService"/>

         <binding.jsonrpc/>

     </service>   

 

    <component name="CalculatorServiceComponent">

              <implementation.java class="calculator.CalculatorServiceImpl"/>

        <reference name="addService" target="AddServiceComponent" />

        <!-- references to SubtractComponent, MultiplyComponent and DivideComponent  -->

    </component>

 

    <component name="AddServiceComponent">

        <implementation.java class="calculator.AddServiceImpl"/>

    </component>

 

    <!-- definitions of SubtractComponent, MultiplyComponent and DivideComponent -->

 

</composite>

我们所做的只是在配置文件中增加个service元素,它告诉Tuscany SCA将CalculatorServiceComponent构件暴露为JSONRPC服务。注意我们并没有修改构件的JAVA代码,只是配置的改变。Helloworld-jsonrpc样例展示了使用jsonrpc绑定的方法,可以参考它来修改计算器应用,使之暴露为JSONRPC服务。如果还想把计算器应用暴露为SOAP/HTTP web service服务,只需作如下更改

<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"

           name="Calculator">

 

     <service name="CalculatorService" promote="CalculatorServiceComponent/CalculatorService">

         <interface.java interface="calculator.CalculatorService"/>

         <!-- ** Below we added info for json binding ** -->

         <binding.jsonrpc/>

         <binding.ws/>

     </service>   

 

    <component name="CalculatorServiceComponent">

              <implementation.java class="calculator.CalculatorServiceImpl"/>

        <reference name="addService" target="AddServiceComponent" />

        <!-- references to SubtractComponent, MultiplyComponent and DivideComponent  -->

    </component>

 

    <component name="AddServiceComponent">

        <implementation.java class="calculator.AddServiceImpl"/>

    </component>

 

    <!-- definitions of SubtractComponent, MultiplyComponent and DivideComponent -->

 

</composite>

这边我们添加了个binding.ws,这样计算器应用就可以同时暴露为JSONRPC服务和web service服务。helloworld-ws-service及helloworld-ws-reference样例展示了如何使用web service绑定形式。

SCA允许其他灵活性。我们可以重新连接构件,如把其中之一作为远程绑定,就像RMI,我们可以使CalculatorServiceComponent构件运行于一台机器,它远程引用其他构件。calculator-rmi-service及calculator-rmi-reference样例展示了RMI绑定形式。

1.8. 使用其他实现方式

我们可以介绍用不同语言实现的构件,如用Ruby实现SubtractServiceComponent构件。

<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"

           name="Calculator">

 

    <component name="CalculatorServiceComponent">

        <implementation.java class="calculator.CalculatorServiceImpl"/>

        <reference name="addService" target="AddServiceComponent" />

        <reference name="subtractService" target="SubtractServiceComponent" />

        <!-- references to MultiplyComponent and DivideComponent  -->

    </component>

 

    <component name="AddServiceComponent">

        <implementation.java class="calculator.AddServiceImpl"/>

    </component>

 

    <component name="SubtractServiceComponent">

        <implementation.script script="calculator/SubtractServiceImpl.rb"/>

    </component>

 

    <!-- definitions of MultiplyComponent and DivideComponent -->

 

</composite>  

SubtractServiceComponent Ruby实现如下

def subtract(n1, n2)

    return n1 - n2

end

Tuscany SCA运行时环境处理Java构件与Ruby构件间的连接及必要的数据转换。calculator-script样例展示了使用不同脚本语言实现构件的方法。

所以用SCA装配的应用具有较强的可扩展性及可整合性。

原创粉丝点击