7.8. 连线(wire)
Wire是用来连接同一composite中的reference和service。
定义wire有两种方法:一是使用reference的属性target,第二种是使用wire连线
7.8.1. 使用reference的属性target
Ø 删除原来的wire那根线
图7_8_1
Ø 在RestaurantServiceComponent的reference billService上设置target属性,可以从target2中选择可用的service
图7_8_2
保存后,会显示一根黄色的wire连线
图7_8_3
Ø 运行TipServiceServer和RestaurantServiceServer, 用soapUI测试,运行后得到bill结果
Ø 打开Restaurant2.composite,可以看到reference billservice上的target的定义, target的格式是<component-name>/<service-name>
<sca:component name="RestaurantServiceComponent">
<sca:implementation.java class="restaurant2.lib.RestaurantServiceImpl"/>
<sca:reference name="menuService" autowire="false"/>
<sca:reference name="billService" target="BillServiceComponent/BillService"/>
<sca:service name="RestaurantService">
<sca:interface.wsdl interface="http://api.restaurant2/#wsdl.interface(RestaurantService)"/>
<sca:binding.ws uri="http://localhost:8085/RestaurantService"/>
</sca:service>
</sca:component>
7.8.2. 通过wire连线定义
黑色的实线就是wire连线。
图7_8_4
打开Restaurant2.composite,可以看到reference menuservice上的wire的定义
<sca:composite xmlns:frascati="http://frascati.ow2.org" xmlns:instance="http://www.w3.org/2004/08/wsdl-instance" xmlns:sawsdl="http://www.w3.org/ns/sawsdl" xmlns:sca="http://www.osoa.org/xmlns/sca/1.0" xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0" name="Restaurant2" targetNamespace="http://eclipse.org/Restaurant2/src/Restaurant2">
…………
<sca:wire source="RestaurantServiceComponent/menuService" target="MenuServiceComponent/MenuService"/>
</sca:composite>
选中wire连线,在properties中可以查看该wire的属性
图7_8_5
Source和target都是必须的,格式分别为<component-name>/<reference-name>,<component-name>/<service-name>
7.8.3. wire的条件
必须满足以下条件才能wire source(reference)到target(service):
Ø source的interface与target的interface必须同时为远程接口或同时为本地接口
Ø target interface上的operation必须与source的interface的operation相同,或者要么前者是后者的超集。
Ø 对于一个operation,名字、输入参数类型和输出参数类型必须都相同。
Ø 输入参数类型与输出参数类型的顺序也必须相同。
Ø source期望的Fault和Exception集必须与target上说明的相同,或者前者是后者的超集。
Ø 两个接口的其他的属性必须相互匹配,包括scope和callback interface。
7.8.4. 编程注意
Service的客户端(reference就是service的客户端,当然其他调用service的程序也称为service的客户端)不能在运行时试图获取service实现的其他接口。比如service的实现,就是component的implementation,中定义了10个operations,而在service的interface中只声明了4个,那个service的客户端只能用这4个operations,不能试图获取其他六个方法。在java中我们可以用instanceof判断是不是某个类,然后强制转换类型,就可以调用该类里面的方法。在这里是不可以这么做的。 SCA的实现(tuscany就是一个SCA实现)可能给所有的wires都使用proxy,所以传到客户端里的对象(service object)只是业务接口,并不是真正的实现,即使interface是local的,客户端和service运行在同一进程中,也是不可以的。
7.8.5. autowire 自动连线
7.8.5.1. 说明
autowire用来简化composite的装配。自动连线可以让component reference自动连线到满足的component service上,而不需要显示的创建连线。启用自动连线后,没有被promote的service 和没有被显示连线的component reference会自动连线到同一composite中的某个符合条件,interface相匹配的service。默认不使用自动连线。通过autowire属性来设置使用与否。composite,component 和Reference上都可以设置autowire属性。从上到下是继承关系。如果下层没有显式说明autowire属性,则使用上层元素的设置。如果该层有设置,那么就使用自己设置的值。比如reference上显示设置autowire属性为false,那么该reference上就不使用autowire功能,不管上层component和composite上怎么设置。
图7_8_6
7.8.5.2. 查找target原则和处理目标service的方式
如果reference使用自动连线,则在composite中查找与该reference相兼容的service。条件是:
Ø Service的interface必须与reference的interface兼容,看14.8.3。
Ø Service上intents,policy sets和bindings必须与reference上的相兼容
如果对于一个reference,查找到了多于1个的service,那么要看reference的multiplicity设置:
Ø 对于multiplicity为0..1和1..1的,SCA运行时会选择其中一个service连线
Ø 对于multiplicity为0..n和1..n的,将引用连线到所有的service。
如果对于一个reference,没有查找到可用service,那么也要看multiplicity设置:
Ø 对于multiplicity为0..1和0..n的,没有问题。
Ø 对于multiplicity为1..1和1..n的,因为reference必须要连到service,运行时会报错
7.8.5.3. 例子
Ø 设置在RestaurantServiceComponent的reference menuService上属性autowire为true
图7_8_7
保存后会发现原来的wire变红,这个wire需要被删掉
图7_8_8
Ø 删掉原来的wire
图7_8_9
Ø 运行TipServiceServer和RestaurantServiceServer, 用soapUI测试,调用getMenu,会得到
图7_8_10
Ø 如果现在把autowire改为false,再运行测试,会得到NPE
Jul 8, 2010 2:22:59 PM org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceInOutSyncMessageReceiver invokeBusinessLogic
SEVERE: java.lang.NullPointerException
org.osoa.sca.ServiceRuntimeException: java.lang.NullPointerException
…… ……
Caused by: java.lang.NullPointerException
at restaurant2.lib.RestaurantServiceImpl.getMenus(RestaurantServiceImpl.java:33)
7.8.5.4. 例子演示autowire的多种情况
Ø 创建一个新的project
图7_8_11
Ø 创建一个新composite
图7_8_12
AutoWiredReferences.composite 内容为:
Ø 创建接口类
Ø 创建实现类
Ø 新建测试类
Ø 运行测试类,结果
Jul 8, 2010 4:37:51 PM org.apache.tuscany.sca.node.impl.NodeImpl <init>
INFO: Creating node: AutoWiredReferences.composite
Jul 8, 2010 4:37:52 PM org.apache.tuscany.sca.node.impl.NodeImpl configureNode
INFO: Loading contribution: file:/D:/eclipse-3.5.2/workspace/reference-autowire/bin/
Jul 8, 2010 4:37:54 PM org.apache.tuscany.sca.assembly.builder.impl.ComponentConfigurationBuilderImpl
WARNING: Component reference multiplicity incompatible with reference multiplicity: Component = AComponent Reference = dReferences
Jul 8, 2010 4:37:54 PM org.apache.tuscany.sca.assembly.builder.impl.ComponentConfigurationBuilderImpl
WARNING: Component reference multiplicity incompatible with reference multiplicity: Component = AComponent Reference = dReferenceArray
Jul 8, 2010 4:37:54 PM org.apache.tuscany.sca.assembly.builder.impl.ComponentConfigurationBuilderImpl
WARNING: Component reference multiplicity incompatible with reference multiplicity: Component = AComponent Reference = dServiceReferences
Jul 8, 2010 4:37:54 PM org.apache.tuscany.sca.assembly.builder.impl.CompositeBindingURIBuilderImpl
WARNING: Component reference multiplicity incompatible with reference multiplicity: Component = AComponent Reference = dReferences
Jul 8, 2010 4:37:54 PM org.apache.tuscany.sca.assembly.builder.impl.CompositeBindingURIBuilderImpl
WARNING: Component reference multiplicity incompatible with reference multiplicity: Component = AComponent Reference = dReferenceArray
Jul 8, 2010 4:37:54 PM org.apache.tuscany.sca.assembly.builder.impl.CompositeBindingURIBuilderImpl
WARNING: Component reference multiplicity incompatible with reference multiplicity: Component = AComponent Reference = dServiceReferences
Jul 8, 2010 4:37:54 PM org.apache.tuscany.sca.assembly.builder.impl.ComponentReferenceWireBuilderImpl
WARNING: No targets for reference: Composite = {http://foo}AutowireReferences Reference = dReference1
Jul 8, 2010 4:37:54 PM org.apache.tuscany.sca.node.impl.NodeImpl start
INFO: Starting node: AutoWiredReferences.composite
1.cReference-autowire(true):wire cReference to CComponent
WIRED COMPONENT NAME: CComponent
2.dReference-autowire(true):wire dReference to DComponent
WIRED COMPONENT NAME: DComponent
3.dReferences-autowire(true):wire dReference to DComponent and DComponent1
WIRED COMPONENT NAME: DComponent,DComponent1
4.dReference-autowire(false):not wire dReference to any service
nullpointer Exception:
5.dReferenceArray-autowire(true):wire dReferenceArray to DComponent and DComponent1
WIRED COMPONENT NAME: DComponent,DComponent1
6.dServiceReferences-autowire(false)-wire(by target):wire dServiceReferences to DComponent and DComponent1
WIRED COMPONENT NAME: DComponent,DComponent1
结果中每个case都有说明,就不额外讲了。