废话不多说,具体示例更能让大家领会BPEL和WebService技术。
示例目的:用BPEL调用通过CXF项目公布的一个加法服务和减法服务,从而形成一个新服务-----运算服务并生成运算服务的wsdl文件。
工具:开发工具使用Eclipse3.5.1,技术框架使用Eclipse-BPEL和Apache ODE,服务器是Tomcat6.0,JDK1.6。
创建服务步骤:
1、首先创建一个java项目,名字叫“AddService”。在该项目下创建属于“com.bpel.sample.caculator.add”包的接口“AddInterface”,增加方法“add”。
2、为该项目添加CXF2.2.5的jar包(不知道如何添加jar包或者如何添加CXF的jar包的读者请自行百度)。
3、利用该java项目生成CXF项目,不知道如何生成CXF项目的请参考这篇文章:使用CXF2.1的STP插件开发WebService。参考该文章时请注意,可能本人的Eclipse插件安装不够完善,或者写该篇文章的作者当时Eclipse版本比较老,本人的Eclipse3.5.1在安装了SOA相关插件后不能按照JAX-WS Java First Project创建模式成功创建CXF项目。Eclipse插件安装的很完善的朋友可以找本人交流,本人QQ:371319819。soa技术交流群:18748450,此群常满,可以加另外的群:162837831
通过上面的步骤,生成了一系列的java类和wsdl文件,下面列出两个关键java类的源码:
AddInterface.java
package com.bpel.sample.caculator.add;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
@WebService(name = "AddInterface", targetNamespace = "http://add.caculator.sample.bpel.com/", wsdlLocation = "WEB-INF/wsdl/AddService.wsdl")
public interface AddInterface {
@WebMethod(operationName="add", action="urn:Add")
public abstract double add(@WebParam(name="arg0") double d, @WebParam(name="arg1") double d1);
}
AddInterfaceImpl.java
package com.bpel.sample.caculator.add;
import javax.jws.WebMethod;
import javax.jws.WebService;
/**
* This class was generated by Apache CXF 2.2.5
* Fri Feb 05 14:02:38 CST 2010
* Generated source version: 2.2.5
*
*/
@WebService(endpointInterface = "com.bpel.sample.caculator.add.AddInterface", serviceName = "AddInterfaceService")
public class AddInterfaceImpl implements AddInterface {
@WebMethod(operationName="add", action="urn:Add")
public double add(double arg0,double arg1) {
System.out.println("AddInterfaceService is called.");
return arg0 + arg1;
}
}
4、完善自动生成的wsdl文件。第一次发帖,没找到附件上传功能,本人下面将wsdl源码贴出来供大家参考。
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="AddInterfaceService"
targetNamespace="http://add.caculator.sample.bpel.com/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://add.caculator.sample.bpel.com/"
xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://add.caculator.sample.bpel.com/" targetNamespace="http://add.caculator.sample.bpel.com/" version="1.0">
<xs:element name="add" type="tns:add"/>
<xs:element name="addResponse" type="tns:addResponse"/>
<xs:complexType name="add">
<xs:sequence>
<xs:element name="arg0" type="xs:double"/>
<xs:element name="arg1" type="xs:double"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="addResponse">
<xs:sequence>
<xs:element name="return" type="xs:double"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="addResponse">
<wsdl:part name="parameters" element="tns:addResponse">
</wsdl:part>
</wsdl:message>
<wsdl:message name="add">
<wsdl:part name="parameters" element="tns:add">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="AddInterface">
<wsdl:operation name="add">
<wsdl:input name="add" message="tns:add">
</wsdl:input>
<wsdl:output name="addResponse" message="tns:addResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="AddInterfaceServiceSoapBinding" type="tns:AddInterface">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="add">
<soap:operation soapAction="urn:Add" style="document"/>
<wsdl:input name="add">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="addResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="AddInterfaceService">
<wsdl:port name="AddInterfacePort" binding="tns:AddInterfaceServiceSoapBinding">
<soap:address location="http://localhost:8080/AddService/services/AddService"/>
</wsdl:port>
</wsdl:service>
<plnk:partnerLinkType name="AddLink">
<plnk:role name="AddProvider" portType="tns:AddInterface"/>
</plnk:partnerLinkType>
</wsdl:definitions>
5、在由java项目生成CXF项目过程中,还会生成有cxf-servlet.xml文件,该文件在部署时可能会出现异常,可以将该xml文件头改成如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:soap="http://cxf.apache.org/bindings/soap"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
6、按照以上步骤,一个加法的Web Service项目已经生成了,为了节省篇幅,按照类似步骤生成的减法Web Service项目这里就忽略了,读者可以自己创建。
7、以上创建的加减法项目可以部署到Tomcat里面去,启动服务器,在IE中输入类似于:http://localhost:8080/AddService/services/AddService/add?arg0=2&arg1=3的语句可以看到返回结果。
8、创建BPEL项目“AddAndSubBpel”,在该项目下创建异步bpel文件“CaculatorBpel”,命名空间“http://caculator.sample.bpel.com/client/”,不会创建bpel项目的朋友请参考这篇文章学习:使用 Eclipse BPEL 插件开发和执行 WS-BPEL V2.0 业务流程,这是IBM官方网站上公布的一个bpel创建教程,可能需要账号才能查看这篇文章。
9、目前本人的bpel流程逻辑是:有三个输入参数,第一个和第二个是两个double数据,用于进行加减法调用,第三个参数是个字符串,可能值为“add”或者“sub”,如果流程发现第三个参数是“add”,将调用外部服务的加法服务,如果是“sub”,将调用减法服务。不过本人目前还在学习Eclipse bpel的结构活动语法,还没进行完整测试。目前的功能是直接调用加法服务,读这篇文章的朋友请明白这一点,懂Eclipse bpel或者想一起学习的朋友请和我一起学习进步。
10、将上面创建的加法服务和减法服务时生成的两个wsdl文件各拷贝一份到该bpel项目下,和bpel文件放在同个目录下。
11、按照逻辑修改自动生成的wsdl文件:CaculatorBpelArtifacts.wsdl,该wsdl文件的完整代码如下:
<?xml version="1.0"?>
<definitions name="CaculatorBpel"
targetNamespace="http://caculator.sample.bpel.com/client/"
xmlns:tns="http://caculator.sample.bpel.com/client/"
xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:bpel="http://docs.oasis-open.org/wsbpel/2.0/process/executable"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:ns1="http://add.caculator.sample.bpel.com/" xmlns:ns2="http://sub.caculator.sample.bpel.com/">
<bpel:import namespace="http://sub.caculator.sample.bpel.com/" location="SubstractService.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"/>
<bpel:import namespace="http://add.caculator.sample.bpel.com/" location="AddService.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"/>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TYPE DEFINITION - List of types participating in this BPEL process
The BPEL Designer will generate default request and response types
but you can define or import any XML Schema type and use them as part
of the message types.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<types>
<schema attributeFormDefault="unqualified" elementFormDefault="qualified"
targetNamespace="http://caculator.sample.bpel.com/client/"
xmlns="http://www.w3.org/2001/XMLSchema">
<element name="CaculatorBpelRequest">
<complexType>
<sequence>
<element name="arg0" type="double"/>
<element name="arg1" type="double"/>
<element minOccurs="0" name="arg2" type="string"/>
</sequence>
</complexType>
</element>
<element name="CaculatorBpelResponse">
<complexType>
<sequence>
<element name="return" type="double"/>
</sequence>
</complexType>
</element>
</schema>
</types>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MESSAGE TYPE DEFINITION - Definition of the message types used as
part of the port type defintions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<message name="CaculatorBpelRequestMessage">
<part name="payload" element="tns:CaculatorBpelRequest"/>
</message>
<message name="CaculatorBpelResponseMessage">
<part name="payload" element="tns:CaculatorBpelResponse"/>
</message>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PORT TYPE DEFINITION - A port type groups a set of operations into
a logical service unit.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- portType implemented by the CaculatorBpel BPEL process -->
<portType name="CaculatorBpel">
<operation name="process">
<input message="tns:CaculatorBpelRequestMessage" />
<output message="tns:CaculatorBpelResponseMessage"/>
</operation>
</portType>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PARTNER LINK TYPE DEFINITION
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<plnk:partnerLinkType name="CaculatorBpel">
<plnk:role name="CaculatorBpelProvider" portType="tns:CaculatorBpel"/>
</plnk:partnerLinkType>
<binding name="CaculatorBinding" type="tns:CaculatorBpel">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="process">
<soap:operation
soapAction=""/>
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
<service name="CaculatorService">
<port name="CaculatorPort" binding="tns:CaculatorBinding">
<soap:address location="http://localhost:8080/ode/processes/CaculatorBpel" />
</port>
</service>
</definitions>
12、修改bpel文件,最终的代码如下:
<!-- CaculatorBpel BPEL Process [Generated by the Eclipse BPEL Designer] -->
<bpel:process name="CaculatorBpel"
targetNamespace="http://caculator.sample.bpel.com/client/"
suppressJoinFailure="yes"
xmlns:tns="http://caculator.sample.bpel.com/client/"
xmlns:bpel="http://docs.oasis-open.org/wsbpel/2.0/process/executable"
xmlns:ns1="http://add.caculator.sample.bpel.com/" xmlns:ns2="http://sub.caculator.sample.bpel.com/">
<!-- Import the client WSDL -->
<bpel:import namespace="http://sub.caculator.sample.bpel.com/" location="SubstractService.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"></bpel:import>
<bpel:import namespace="http://add.caculator.sample.bpel.com/" location="AddService.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"></bpel:import>
<bpel:import location="CaculatorBpelArtifacts.wsdl" namespace="http://caculator.sample.bpel.com/client/"
importType="http://schemas.xmlsoap.org/wsdl/" />
<!-- ================================================================= -->
<!-- PARTNERLINKS -->
<!-- List of services participating in this BPEL process -->
<!-- ================================================================= -->
<bpel:partnerLinks>
<!-- The 'client' role represents the requester of this service. -->
<bpel:partnerLink name="client"
partnerLinkType="tns:CaculatorBpel"
myRole="CaculatorBpelProvider"
/>
<bpel:partnerLink name="AddLink" partnerLinkType="ns1:AddLink" partnerRole="AddProvider"></bpel:partnerLink>
<bpel:partnerLink name="SubLink" partnerLinkType="ns2:SubstractLink" partnerRole="SubstractProvider"></bpel:partnerLink>
</bpel:partnerLinks>
<!-- ================================================================= -->
<!-- VARIABLES -->
<!-- List of messages and XML documents used within this BPEL process -->
<!-- ================================================================= -->
<bpel:variables>
<!-- Reference to the message passed as input during initiation -->
<bpel:variable name="input"
messageType="tns:CaculatorBpelRequestMessage"/>
<!--
Reference to the message that will be returned to the requester
-->
<bpel:variable name="output"
messageType="tns:CaculatorBpelResponseMessage"/>
<bpel:variable name="AddLinkRequest" messageType="ns1:add"></bpel:variable>
<bpel:variable name="AddLinkResponse" messageType="ns1:addResponse"></bpel:variable>
</bpel:variables>
<!-- ================================================================= -->
<!-- ORCHESTRATION LOGIC -->
<!-- Set of activities coordinating the flow of messages across the -->
<!-- services integrated within this business process -->
<!-- ================================================================= -->
<bpel:sequence name="main">
<!-- Receive input from requester.
Note: This maps to operation defined in CaculatorBpel.wsdl
-->
<bpel:receive name="receiveInput" partnerLink="client"
portType="tns:CaculatorBpel"
operation="process" variable="input"
createInstance="yes"/>
<!-- Generate reply to synchronous request -->
<bpel:assign validate="no" name="Assign">
<bpel:copy>
<bpel:from>
<bpel:literal xml:space="preserve"><tns:add xmlns:tns="http://add.caculator.sample.bpel.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<arg0></arg0>
<arg1></arg1>
</tns:add></bpel:literal>
</bpel:from>
<bpel:to part="parameters" variable="AddLinkRequest"></bpel:to>
</bpel:copy>
<bpel:copy>
<bpel:from part="payload" variable="input">
<bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0">
<![CDATA[tns:arg0]]>
</bpel:query>
</bpel:from>
<bpel:to part="parameters" variable="AddLinkRequest">
<bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0">
<![CDATA[arg0]]>
</bpel:query>
</bpel:to>
</bpel:copy>
<bpel:copy>
<bpel:from part="payload" variable="input">
<bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0">
<![CDATA[tns:arg1]]>
</bpel:query>
</bpel:from>
<bpel:to part="parameters" variable="AddLinkRequest">
<bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0">
<![CDATA[arg1]]>
</bpel:query>
</bpel:to>
</bpel:copy>
</bpel:assign>
<bpel:invoke name="Invoke" partnerLink="AddLink" operation="add" portType="ns1:AddInterface" inputVariable="AddLinkRequest" outputVariable="AddLinkResponse"></bpel:invoke>
<bpel:assign validate="no" name="Assign1">
<bpel:copy>
<bpel:from>
<bpel:literal xml:space="preserve"><tns:CaculatorBpelResponse xmlns:tns="http://caculator.sample.bpel.com/client/">
<tns:return></tns:return>
</tns:CaculatorBpelResponse></bpel:literal>
</bpel:from>
<bpel:to part="payload" variable="output">
</bpel:to>
</bpel:copy>
<bpel:copy>
<bpel:from part="parameters" variable="AddLinkResponse">
<bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"><![CDATA[return]]></bpel:query>
</bpel:from>
<bpel:to part="payload" variable="output">
<bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"><![CDATA[tns:return]]></bpel:query>
</bpel:to>
</bpel:copy>
</bpel:assign>
<bpel:reply name="replyOutput"
partnerLink="client"
portType="tns:CaculatorBpel"
operation="process"
variable="output"
/>
</bpel:sequence>
</bpel:process>
13、生成deploy.xml文件,Eclipse工具本来可以通过可视化界面生成deploy文件的,但是可能还是本人插件安装的不够完好,在生成deploy文件时总会出现一些异常,按照网上前辈的方式创建时不能得到理想的效果,还好deploy.xml文件不大而且逻辑上也很清晰,可以手动创建,源码如下:
<?xml version="1.0" encoding="UTF-8"?>
<deploy xmlns="http://ode.fivesight.com/schemas/2006/06/27/dd"
xmlns:pns="http://caculator.sample.bpel.com/client/"
xmlns:wns="http://caculator.sample.bpel.com/client/"
xmlns:ns1="http://add.caculator.sample.bpel.com/"
xmlns:ns2="http://sub.caculator.sample.bpel.com/">
<process name="pns:CaculatorBpel">
<active>true</active>
<provide partnerLink="client">
<service name="wns:CaculatorService" port="CaculatorPort"/>
</provide>
<invoke partnerLink="AddLink">
<service name="ns1:AddInterfaceService" port="AddInterfacePort"/>
</invoke>
<invoke partnerLink="SubLink">
<service name="ns2:SubstractInterfaceService" port="SubstractInterfacePort"/>
</invoke>
</process>
</deploy>
14、至此,一个通过bpel调用Web Service的案例已经完成了。将该bpel项目部署到ode的process目录里,确保已经启动成功Tomcat,在IE中输入http://localhost:8080/ode/processes/CaculatorBpel/process?arg0=111.0&arg1=3.0&arg2=add,按理应该能得到想要的效果。
15、如果希望能够通过java调用bpel流程文件,在上面的:使用 Eclipse BPEL 插件开发和执行 WS-BPEL V2.0 业务流程教程中可以得到一些启发,不过当前soa相关框架版本变化比较频繁,还有jar包版本的问题,可能网上有些前辈给出的开发步骤或者源码未必能适用,这个需要大家慢慢琢磨。
本人也是初学soa相关技术,在学习过程中,包括筛选,搭建开发工具,测试部署网上案例,这期间走了不少弯路,也花费了很多精力,虽然有时穷几天的时间才能一点一滴地领会一点点相关知识,但是积少成多,希望能和对soa感兴趣的网友一起交流进步,尽快掌握这方面的技术,抛砖引玉,欢迎交流。
1 楼
hbdrawn
2010-04-08
invoke两个WS是没有问题的,但要是部署一个异步流程呢,其中流程调用的是另一个流程暴露的WS接口,提示no service name about my role for partnerlinkB