Tuscany SCA案例分析(二)(连载中...)
2008-01-08 12:04
218 查看
今天给大家讲的是calculator的分布式版本,在这个案例中,我们先来看看其设计图,如下:
从图中可以明显地看出有3个节点nodeA,nodeB,nodeC,而nodeA上有三个组件,nodeB和nodeC上分别有一个组件。这3个节点在同一个domain中。服务引用的关系在这里就不多说了。
那么我们下面进入开发过程了。
先建立一个普通的java project,项目名叫"MyDistributedCalculator",默认设置
在书写主要的业务逻辑单元代码之前,先象案例一一样,加入MyTuscany用户库,好,现在集中精力书写逻辑代码,因为这里对案例一有一个承接关系,所以建议看案例二之前先看明白案例一。我们这里将案例一项目中的calculator包下的除CalculatorClient.java文件外的java文件都copy到myDistributedCalculator项目的calculator包下。如下图:
这里绝大部分代码和案例一都一样,只是因为分布式的原因,所以就要修改几个接口部分的代码,因为AddServiceComponent和SubtractServiceComponent都在另外的机子上,所以在他们相应的服务接口上要声明为@Remotable,以便让nodeA上的CalculatorServiceComponent远程引用,这和案例一是不一样的地方。这里给出他们修改后的代码:
/**//*文件AddService.java*/
package calculator;
import org.osoa.sca.annotations.Remotable;
/** *//**
* The Add service interface
*/
@Remotable
public interface AddService ...{
double add(double n1, double n2);
}
/**//*文件SubtractService.java*/
package calculator;
import org.osoa.sca.annotations.Remotable;
/** *//**
* The interface for the multiply service
*/
@Remotable
public interface SubtractService ...{
double subtract(double n1, double n2);
}
接下来要做的就是要写一个domain manager类和node启动类,我们先建立node包,然后建立相应的文件,其中用于启动domain manager类的文件名为DomainNode.java,用于启动node的类文件名为CalculatorNode.java
他们分别的内容为:
/**//*CalculatorNode.java文件内容如下*/
package node;
import java.io.IOException;
import javax.xml.namespace.QName;
import org.apache.tuscany.sca.domain.SCADomain;
import org.apache.tuscany.sca.node.SCANode;
import org.apache.tuscany.sca.node.SCANodeFactory;
import calculator.CalculatorService;
/** *//**
* This client program shows how to run a distributed SCA node. In this case a
* calculator node has been constructed specifically for running the calculator
* composite. Internally it creates a representation of a node and associates a
* distributed domain with the node. This separation is made different implementations
* of the distributed domain can be provided.
*/
public class CalculatorNode ...{
public static void main(String[] args) throws Exception ...{
// Check that the correct arguments have been provided
if (null == args || args.length < 2) ...{
System.err.println("Useage: java CalculatorNode domainname nodename");
System.exit(1);
}
try ...{
String domainName = args[0];
String nodeName = args[1];
ClassLoader cl = CalculatorNode.class.getClassLoader();
SCANodeFactory nodeFactory = SCANodeFactory.newInstance();
SCANode node = nodeFactory.createSCANode(nodeName, domainName);
node.addContribution(nodeName, cl.getResource(nodeName + "/"));
//System.out.println(cl.getResource(nodeName + "/").toString());
node.deployComposite(new QName("http://sample", "Calculator"));
node.start();
// nodeA is the head node and runs some tests while all other nodes
// simply listen for incoming messages
if ( nodeName.equals("nodeA") ) ...{
// do some application stuff
CalculatorService calculatorService =
node.getDomain().getService(CalculatorService.class, "CalculatorServiceComponentA");
// Calculate
System.out.println("3 + 2=" + calculatorService.add(3, 2));
System.out.println("3 - 2=" + calculatorService.subtract(3, 2));
System.out.println("3 * 2=" + calculatorService.multiply(3, 2));
System.out.println("3 / 2=" + calculatorService.divide(3, 2));
// a little hidden loop test to put some load on the nodes
if (args.length > 2)...{
for (int i=0; i < 1000; i++)...{
// Calculate
System.out.println("3 + 2=" + calculatorService.add(3, 2));
System.out.println("3 - 2=" + calculatorService.subtract(3, 2));
System.out.println("3 * 2=" + calculatorService.multiply(3, 2));
System.out.println("3 / 2=" + calculatorService.divide(3, 2));
}
}
} else ...{
// start up and wait for messages
try ...{
System.out.println("Node started (press enter to shutdown)");
System.in.read();
} catch (IOException e) ...{
e.printStackTrace();
}
}
// stop the node and all the domains in it
node.stop();
} catch(Exception ex) ...{
System.err.println("Exception in node - " + ex.getMessage());
ex.printStackTrace(System.err);
}
}
}
/**//*DomainNode.java 文件内容如下*/
package node;
import org.apache.tuscany.sca.domain.SCADomain;
import org.apache.tuscany.sca.domain.SCADomainFactory;
/** *//**
* This server program that loads a composite to provide simple registry function.
* This server can be replaced with any registry that is appropriate but the components
* in each node that talk to the registry should be replaced also.
*/
public class DomainNode ...{
private static String DEFAULT_DOMAIN_URI = "http://localhost:8877";
public static void main(String[] args) ...{
try ...{
SCADomainFactory domainFactory = SCADomainFactory.newInstance();
SCADomain domain = domainFactory.createSCADomain(DEFAULT_DOMAIN_URI);
domain.start();
System.out.println("Domain started (press enter to shutdown)");
System.in.read();
domain.stop();
} catch (Exception e) ...{
e.printStackTrace();
}
System.out.println("Domain stopped");
}
}
这里将我自己的理解和对代码的分析写下来:
先从DomainNode.java开始分析,里面用到了两个类,SCADomainFactory 和SCADomain。代码比较简单,就是用SCADomainFactory 本身的newInstance()生成自己的实例,然后通过createSCADomain()函数生成SCADomain的实例,然后用domain.start();启动domain。这里要特别注意的是,虽然代码很简单,但其实它完成的工作可不少,首先createSCADomain()会去实例化一个实现了SCADomain接口的类,这里是SCADomainImpl类,通过查看分析tuscany的源代码,发现该类初始化函数调用了init()函数
而在init()函数中完成了一些关键的工作,其中里面有一个就是初始化一些domain manager的服务组件,那么根据什么来初始化这些组件呢,就是根据domain.composite文件,该文件的位置是在tuscany-sca-all-1.0.1-incubating.jar文件内部,如图:
该文件的内容如下:
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://sample"
xmlns:sample="http://sample"
xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0"
name="Domain">
<component name="domain">
<tuscany:implementation.resource location="webroot"/>
<service name="Resource">
<tuscany:binding.http uri="http://localhost:8877/domain"/>
</service>
</component>
<component name="DomainManagerComponent">
<implementation.java class="org.apache.tuscany.sca.domain.impl.DomainManagerServiceImpl"/>
<service name="DomainManagerInitService">
<interface.java interface="org.apache.tuscany.sca.domain.DomainManagerInitService"/>
<binding.sca/>
</service>
<service name="DomainManagerNodeEventService">
<interface.java interface="org.apache.tuscany.sca.domain.DomainManagerNodeEventService"/>
<binding.ws uri="http://localhost:8877/DomainManagerComponent/DomainManagerNodeEventService"/>
</service>
<service name="DomainManagementService">
<interface.java interface="org.apache.tuscany.sca.domain.management.DomainManagementService"/>
<tuscany:binding.jsonrpc uri="http://localhost:8877/DomainManagerComponent/DomainManagementService"/>
</service>
</component>
</composite>
注意到上面的<tuscany:binding.http uri="http://localhost:8877/domain"/>,这里是这些组件注册为相应的servlet时的uri地址,这也就要求DomainNode.java中的private static String DEFAULT_DOMAIN_URI = "http://localhost:8877";必须是domain manager的根地址,必须和tuscany:binding的uri保持一致。到目前为止,我们就解释完DomainNode的内容了,下面我们看看复杂些的CalculatorNode.java的内容。其实他的内容仔细看也不复杂,主干部分的代码功能主要是从命令行中接受两个参数,一个是domainname,一个是nodename,然后根据这些信息来启动node,这里跟前面的DomainNode有点类似,也是先用SCANodeFactory的newInstance()实例化自身,再用createSCANode实例化出一个实现了SCANode接口的类,这里是SCANodeImpl类,该类的初始化函数中也执行了其相应的init()函数,而init()函数则完成了对node管理组件的初始化,是根据tuscany-sca-all-1.0.1-incubating.jar文件内部的node.composite文件,下面将其文件内容列出如下:
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://management"
xmlns:sample="http://management"
xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0"
name="Management">
<component name="DomainManagerComponent">
<implementation.java class="org.apache.tuscany.sca.node.impl.DomainManagerServiceImpl"/>
<reference name="domainManager">
<interface.java interface="org.apache.tuscany.sca.domain.DomainManagerNodeEventService"/>
<binding.ws uri="http://localhost:8878/DomainManagerComponent/DomainManagerNodeEventService"/>
</reference>
</component>
<component name="NodeManagerComponent">
<implementation.java class="org.apache.tuscany.sca.node.impl.NodeManagerServiceImpl"/>
<service name="NodeManagerInitService">
<interface.java interface="org.apache.tuscany.sca.node.NodeManagerInitService"/>
<binding.sca/>
</service>
<service name="NodeManagerService">
<interface.java interface="org.apache.tuscany.sca.node.NodeManagerService"/>
<binding.ws uri="http://localhost:8878/NodeManagerComponent/NodeManagerService"/>
</service>
<service name="ComponentManagerService">
<interface.java interface="org.apache.tuscany.sca.node.ComponentManagerService"/>
<tuscany:binding.jsonrpc uri="http://localhost:8878/NodeManagerComponent/ComponentManagerJson"/>
</service>
</component>
<component name="node">
<tuscany:implementation.resource location="webroot"/>
<service name="Resource">
<tuscany:binding.http uri="http://localhost:8878/node"/>
</service>
</component>
</composite>
通过这些信息再与下图相比来理解吧
好了,这里有点初学者会有点糊涂,看看DomainNode.java就可以知道,先要启动nodeB和nodeC,因为他们是被引用的服务组件,再是启动nodeA,因为它上的CalculatorServiceComponent才能引用到相应的服务。这里有点急了,都忘记要写装配文件.composite文件了,否则怎么装配这些服务呀,执行结果要等到写完正确的装配文件再说,开动吧。先按下图建立目录和文件,写nodeA的composite文件和sca-contribution.xml文件,列出内容如下:
我在分布式SCADomain说明中说了如何加载contribution的,sca-contribution.xml里面就说明了哪些composite可部署,Calculator.composite则告诉了该构件中有哪里组件。
下面给出nodeA下的sca-contribution.xml和Calculator.composite内容:
<!--sca-contribution.xml内容 -->
<?xml version="1.0" encoding="UTF-8"?>
<contribution xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://sample"
xmlns:sample="http://sample">
<deployable composite="sample:Calculator"/>
</contribution>
<!--
Calculator.composite文件内容
-->
<?xml version="1.0" encoding="UTF-8"?>
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://sample"
xmlns:sample="http://sample"
name="Calculator">
<component name="CalculatorServiceComponentA">
<implementation.java class="calculator.CalculatorServiceImpl"/>
<reference name="addService" target="AddServiceComponentB" />
<reference name="subtractService" target="SubtractServiceComponentC" />
<reference name="multiplyService" target="MultiplyServiceComponentA"/>
<reference name="divideService" target="DivideServiceComponentA" />
</component>
<component name="MultiplyServiceComponentA">
<implementation.java class="calculator.MultiplyServiceImpl" />
</component>
<component name="DivideServiceComponentA">
<implementation.java class="calculator.DivideServiceImpl" />
</component>
</composite>
每个相应的node目录下的sca-contribution.xml内容都一样的,不同的只是Calculator.composite里的内容,因为在nodeA中只有两个组件MultiplyServiceComponentA、DivideServiceComponentA还有些引用。其他node的Calculator.composite内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!--
nodeB下的Calculator.composite内容
-->
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://sample"
xmlns:sample="http://sample"
name="Calculator">
<component name="AddServiceComponentB">
<implementation.java class="calculator.AddServiceImpl" />
</component>
</composite>
<?xml version="1.0" encoding="UTF-8"?>
<!--
nodeC下的Calculator.composite内容
-->
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://sample"
xmlns:sample="http://sample"
name="Calculator">
<component name="SubtractServiceComponentC">
<implementation.java class="calculator.SubtractServiceImpl" />
<service name="SubtractService">
<binding.sca uri="http://localhost:8086/SubtractServiceComponentC"/>
</service>
</component>
</composite>
好了,装配的配置文件都搞好了,下面我们来运行下,看看结果如何。
先从eclipse里象启动一般java程序一样启动DomainNode.java
然后再要启动CalculatorNode.java,这里启动要传入不同的参数,这里给出启动nodeB时打开启动对话框配置的传入参数图:
启动nodeC和nodeA的参数只要用nodeC和nodeA替换nodeB就可以了,给出个最终结果图吧,如下:
记住启动的顺序,先要启动nodeB和nodeC,最后启动nodeA呀,成功了记得告诉我,谢谢
从图中可以明显地看出有3个节点nodeA,nodeB,nodeC,而nodeA上有三个组件,nodeB和nodeC上分别有一个组件。这3个节点在同一个domain中。服务引用的关系在这里就不多说了。
那么我们下面进入开发过程了。
先建立一个普通的java project,项目名叫"MyDistributedCalculator",默认设置
在书写主要的业务逻辑单元代码之前,先象案例一一样,加入MyTuscany用户库,好,现在集中精力书写逻辑代码,因为这里对案例一有一个承接关系,所以建议看案例二之前先看明白案例一。我们这里将案例一项目中的calculator包下的除CalculatorClient.java文件外的java文件都copy到myDistributedCalculator项目的calculator包下。如下图:
这里绝大部分代码和案例一都一样,只是因为分布式的原因,所以就要修改几个接口部分的代码,因为AddServiceComponent和SubtractServiceComponent都在另外的机子上,所以在他们相应的服务接口上要声明为@Remotable,以便让nodeA上的CalculatorServiceComponent远程引用,这和案例一是不一样的地方。这里给出他们修改后的代码:
/**//*文件AddService.java*/
package calculator;
import org.osoa.sca.annotations.Remotable;
/** *//**
* The Add service interface
*/
@Remotable
public interface AddService ...{
double add(double n1, double n2);
}
/**//*文件SubtractService.java*/
package calculator;
import org.osoa.sca.annotations.Remotable;
/** *//**
* The interface for the multiply service
*/
@Remotable
public interface SubtractService ...{
double subtract(double n1, double n2);
}
接下来要做的就是要写一个domain manager类和node启动类,我们先建立node包,然后建立相应的文件,其中用于启动domain manager类的文件名为DomainNode.java,用于启动node的类文件名为CalculatorNode.java
他们分别的内容为:
/**//*CalculatorNode.java文件内容如下*/
package node;
import java.io.IOException;
import javax.xml.namespace.QName;
import org.apache.tuscany.sca.domain.SCADomain;
import org.apache.tuscany.sca.node.SCANode;
import org.apache.tuscany.sca.node.SCANodeFactory;
import calculator.CalculatorService;
/** *//**
* This client program shows how to run a distributed SCA node. In this case a
* calculator node has been constructed specifically for running the calculator
* composite. Internally it creates a representation of a node and associates a
* distributed domain with the node. This separation is made different implementations
* of the distributed domain can be provided.
*/
public class CalculatorNode ...{
public static void main(String[] args) throws Exception ...{
// Check that the correct arguments have been provided
if (null == args || args.length < 2) ...{
System.err.println("Useage: java CalculatorNode domainname nodename");
System.exit(1);
}
try ...{
String domainName = args[0];
String nodeName = args[1];
ClassLoader cl = CalculatorNode.class.getClassLoader();
SCANodeFactory nodeFactory = SCANodeFactory.newInstance();
SCANode node = nodeFactory.createSCANode(nodeName, domainName);
node.addContribution(nodeName, cl.getResource(nodeName + "/"));
//System.out.println(cl.getResource(nodeName + "/").toString());
node.deployComposite(new QName("http://sample", "Calculator"));
node.start();
// nodeA is the head node and runs some tests while all other nodes
// simply listen for incoming messages
if ( nodeName.equals("nodeA") ) ...{
// do some application stuff
CalculatorService calculatorService =
node.getDomain().getService(CalculatorService.class, "CalculatorServiceComponentA");
// Calculate
System.out.println("3 + 2=" + calculatorService.add(3, 2));
System.out.println("3 - 2=" + calculatorService.subtract(3, 2));
System.out.println("3 * 2=" + calculatorService.multiply(3, 2));
System.out.println("3 / 2=" + calculatorService.divide(3, 2));
// a little hidden loop test to put some load on the nodes
if (args.length > 2)...{
for (int i=0; i < 1000; i++)...{
// Calculate
System.out.println("3 + 2=" + calculatorService.add(3, 2));
System.out.println("3 - 2=" + calculatorService.subtract(3, 2));
System.out.println("3 * 2=" + calculatorService.multiply(3, 2));
System.out.println("3 / 2=" + calculatorService.divide(3, 2));
}
}
} else ...{
// start up and wait for messages
try ...{
System.out.println("Node started (press enter to shutdown)");
System.in.read();
} catch (IOException e) ...{
e.printStackTrace();
}
}
// stop the node and all the domains in it
node.stop();
} catch(Exception ex) ...{
System.err.println("Exception in node - " + ex.getMessage());
ex.printStackTrace(System.err);
}
}
}
/**//*DomainNode.java 文件内容如下*/
package node;
import org.apache.tuscany.sca.domain.SCADomain;
import org.apache.tuscany.sca.domain.SCADomainFactory;
/** *//**
* This server program that loads a composite to provide simple registry function.
* This server can be replaced with any registry that is appropriate but the components
* in each node that talk to the registry should be replaced also.
*/
public class DomainNode ...{
private static String DEFAULT_DOMAIN_URI = "http://localhost:8877";
public static void main(String[] args) ...{
try ...{
SCADomainFactory domainFactory = SCADomainFactory.newInstance();
SCADomain domain = domainFactory.createSCADomain(DEFAULT_DOMAIN_URI);
domain.start();
System.out.println("Domain started (press enter to shutdown)");
System.in.read();
domain.stop();
} catch (Exception e) ...{
e.printStackTrace();
}
System.out.println("Domain stopped");
}
}
这里将我自己的理解和对代码的分析写下来:
先从DomainNode.java开始分析,里面用到了两个类,SCADomainFactory 和SCADomain。代码比较简单,就是用SCADomainFactory 本身的newInstance()生成自己的实例,然后通过createSCADomain()函数生成SCADomain的实例,然后用domain.start();启动domain。这里要特别注意的是,虽然代码很简单,但其实它完成的工作可不少,首先createSCADomain()会去实例化一个实现了SCADomain接口的类,这里是SCADomainImpl类,通过查看分析tuscany的源代码,发现该类初始化函数调用了init()函数
而在init()函数中完成了一些关键的工作,其中里面有一个就是初始化一些domain manager的服务组件,那么根据什么来初始化这些组件呢,就是根据domain.composite文件,该文件的位置是在tuscany-sca-all-1.0.1-incubating.jar文件内部,如图:
该文件的内容如下:
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://sample"
xmlns:sample="http://sample"
xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0"
name="Domain">
<component name="domain">
<tuscany:implementation.resource location="webroot"/>
<service name="Resource">
<tuscany:binding.http uri="http://localhost:8877/domain"/>
</service>
</component>
<component name="DomainManagerComponent">
<implementation.java class="org.apache.tuscany.sca.domain.impl.DomainManagerServiceImpl"/>
<service name="DomainManagerInitService">
<interface.java interface="org.apache.tuscany.sca.domain.DomainManagerInitService"/>
<binding.sca/>
</service>
<service name="DomainManagerNodeEventService">
<interface.java interface="org.apache.tuscany.sca.domain.DomainManagerNodeEventService"/>
<binding.ws uri="http://localhost:8877/DomainManagerComponent/DomainManagerNodeEventService"/>
</service>
<service name="DomainManagementService">
<interface.java interface="org.apache.tuscany.sca.domain.management.DomainManagementService"/>
<tuscany:binding.jsonrpc uri="http://localhost:8877/DomainManagerComponent/DomainManagementService"/>
</service>
</component>
</composite>
注意到上面的<tuscany:binding.http uri="http://localhost:8877/domain"/>,这里是这些组件注册为相应的servlet时的uri地址,这也就要求DomainNode.java中的private static String DEFAULT_DOMAIN_URI = "http://localhost:8877";必须是domain manager的根地址,必须和tuscany:binding的uri保持一致。到目前为止,我们就解释完DomainNode的内容了,下面我们看看复杂些的CalculatorNode.java的内容。其实他的内容仔细看也不复杂,主干部分的代码功能主要是从命令行中接受两个参数,一个是domainname,一个是nodename,然后根据这些信息来启动node,这里跟前面的DomainNode有点类似,也是先用SCANodeFactory的newInstance()实例化自身,再用createSCANode实例化出一个实现了SCANode接口的类,这里是SCANodeImpl类,该类的初始化函数中也执行了其相应的init()函数,而init()函数则完成了对node管理组件的初始化,是根据tuscany-sca-all-1.0.1-incubating.jar文件内部的node.composite文件,下面将其文件内容列出如下:
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://management"
xmlns:sample="http://management"
xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0"
name="Management">
<component name="DomainManagerComponent">
<implementation.java class="org.apache.tuscany.sca.node.impl.DomainManagerServiceImpl"/>
<reference name="domainManager">
<interface.java interface="org.apache.tuscany.sca.domain.DomainManagerNodeEventService"/>
<binding.ws uri="http://localhost:8878/DomainManagerComponent/DomainManagerNodeEventService"/>
</reference>
</component>
<component name="NodeManagerComponent">
<implementation.java class="org.apache.tuscany.sca.node.impl.NodeManagerServiceImpl"/>
<service name="NodeManagerInitService">
<interface.java interface="org.apache.tuscany.sca.node.NodeManagerInitService"/>
<binding.sca/>
</service>
<service name="NodeManagerService">
<interface.java interface="org.apache.tuscany.sca.node.NodeManagerService"/>
<binding.ws uri="http://localhost:8878/NodeManagerComponent/NodeManagerService"/>
</service>
<service name="ComponentManagerService">
<interface.java interface="org.apache.tuscany.sca.node.ComponentManagerService"/>
<tuscany:binding.jsonrpc uri="http://localhost:8878/NodeManagerComponent/ComponentManagerJson"/>
</service>
</component>
<component name="node">
<tuscany:implementation.resource location="webroot"/>
<service name="Resource">
<tuscany:binding.http uri="http://localhost:8878/node"/>
</service>
</component>
</composite>
通过这些信息再与下图相比来理解吧
好了,这里有点初学者会有点糊涂,看看DomainNode.java就可以知道,先要启动nodeB和nodeC,因为他们是被引用的服务组件,再是启动nodeA,因为它上的CalculatorServiceComponent才能引用到相应的服务。这里有点急了,都忘记要写装配文件.composite文件了,否则怎么装配这些服务呀,执行结果要等到写完正确的装配文件再说,开动吧。先按下图建立目录和文件,写nodeA的composite文件和sca-contribution.xml文件,列出内容如下:
我在分布式SCADomain说明中说了如何加载contribution的,sca-contribution.xml里面就说明了哪些composite可部署,Calculator.composite则告诉了该构件中有哪里组件。
下面给出nodeA下的sca-contribution.xml和Calculator.composite内容:
<!--sca-contribution.xml内容 -->
<?xml version="1.0" encoding="UTF-8"?>
<contribution xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://sample"
xmlns:sample="http://sample">
<deployable composite="sample:Calculator"/>
</contribution>
<!--
Calculator.composite文件内容
-->
<?xml version="1.0" encoding="UTF-8"?>
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://sample"
xmlns:sample="http://sample"
name="Calculator">
<component name="CalculatorServiceComponentA">
<implementation.java class="calculator.CalculatorServiceImpl"/>
<reference name="addService" target="AddServiceComponentB" />
<reference name="subtractService" target="SubtractServiceComponentC" />
<reference name="multiplyService" target="MultiplyServiceComponentA"/>
<reference name="divideService" target="DivideServiceComponentA" />
</component>
<component name="MultiplyServiceComponentA">
<implementation.java class="calculator.MultiplyServiceImpl" />
</component>
<component name="DivideServiceComponentA">
<implementation.java class="calculator.DivideServiceImpl" />
</component>
</composite>
每个相应的node目录下的sca-contribution.xml内容都一样的,不同的只是Calculator.composite里的内容,因为在nodeA中只有两个组件MultiplyServiceComponentA、DivideServiceComponentA还有些引用。其他node的Calculator.composite内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!--
nodeB下的Calculator.composite内容
-->
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://sample"
xmlns:sample="http://sample"
name="Calculator">
<component name="AddServiceComponentB">
<implementation.java class="calculator.AddServiceImpl" />
</component>
</composite>
<?xml version="1.0" encoding="UTF-8"?>
<!--
nodeC下的Calculator.composite内容
-->
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
targetNamespace="http://sample"
xmlns:sample="http://sample"
name="Calculator">
<component name="SubtractServiceComponentC">
<implementation.java class="calculator.SubtractServiceImpl" />
<service name="SubtractService">
<binding.sca uri="http://localhost:8086/SubtractServiceComponentC"/>
</service>
</component>
</composite>
好了,装配的配置文件都搞好了,下面我们来运行下,看看结果如何。
先从eclipse里象启动一般java程序一样启动DomainNode.java
然后再要启动CalculatorNode.java,这里启动要传入不同的参数,这里给出启动nodeB时打开启动对话框配置的传入参数图:
启动nodeC和nodeA的参数只要用nodeC和nodeA替换nodeB就可以了,给出个最终结果图吧,如下:
记住启动的顺序,先要启动nodeB和nodeC,最后启动nodeA呀,成功了记得告诉我,谢谢
相关文章推荐
- Tuscany SCA案例分析(一)(连载中...)
- Tuscany SCA启动过程分析(组图)
- Tuscany SCA启动过程分析
- 非正式案例分析:产品背后还藏了些什么?
- Java之JVM调优案例分析与实战(3) - 堆外内存导致的溢出错误
- 简单分析一个通过 js 劫持进行案例
- IDC机房KVM应用案例分析
- WebLogic集群案例分析
- oracle的存储过程和存储函数深入分析和案例
- 软件产品案例分析
- 真实案例:使用Java Thread Dump分析ReadWriteLock导致的死锁问题
- rvest爬虫及案例分析
- Windows蓝屏案例分析
- 指针的灵活使用(分析Device tree案例)
- iptables DNAT功能介绍及案例分析
- [案例分析]一汽高工离职后揭示的中国汽车业绝对内幕!(转)
- 基于Tuscany的Web应用程序分析
- 首次接触jfreechart案例分析
- Sql语句优化之explan分析案例
- 分析函数案例二