文章
![]() |
SOA 最佳实践: BPEL 指南 |
|
第 4 部分: 使用 WSIF 进行集成 了解 BPEL 流程如何使用 WSIF 访问 Java 类和 EJB。
2005 年 10 月发布 在现实情况中,BPEL 业务流程通常必须连接到现有的应用程序或系统。 本文主要介绍与 J2EE 组件的连通性,如 Java 类、Enterprise Java Bean (EJB)、Java 消息服务 (JMS)、可以通过 Java Connector Architecture (JCA) 访问的 ERP 系统、JDBC 数据库或其他 Java 资源。 尽管可以将这些资源转换为 Web 服务,但该做法存在几个缺点:
在 BPEL 指南的这一部分中,您将了解 BPEL 流程如何使用 WSIF 访问 Web 服务以外的资源。 了解 WSIF 设想一个购买图书的业务流程。 此异步流程包含三个 Web 服务: 一个图书等级 Web 服务(返回从 0 到 5(最好)的图书等级)和用于两个相同书店服务的 Web 服务(返回图书价格)。 该流程选择较低的价格,然后完成购买。 本示例定义了故障处理程序,并将该流程分成多个作用域(参见 1_BuyBook\BuyBook.bpel)。 假设为了获取图书等级,您倾向于使用一个 Java 类、EJB(会话 bean)、可以通过 JCA 访问的企业信息系统中的服务或一个类似的 Java 资源。 要使用 Oracle BPEL 流程管理器将这些资源(可能还包括存在绑定的任何其他资源)整合到 BPEL 流程中,您只需修改服务绑定 (WSDL) 而非 BPEL 流程本身。 因此,要使用 Java 类替换图书等级 Web 服务,只需修改此 Web 服务的 WSDL(稍后将对其进行详细介绍)。 WSIF(最初由 IBM alphaWorks 在它的 Web 服务工具包中开发的一种 Apache 技术)是实现该方法的基本技术。 即使它不是通过 SOAP 通信的 Web 服务,它仍然可以使您在 WSDL 中描述 Web 服务,从而扩展了 Web 服务模型。 WSIF 还使您可以将这样的服务映射到实际的实现和协议。 换言之,您可以将 BPEL 流程中使用的任何合作伙伴 Web 服务的抽象描述绑定到相应的资源,而该资源可以使用某个受支持的 WSIF 绑定进行通信。 Oracle BPEL 流程管理器 10.1.2 使用的 WSIF 支持 Java 类、EJB、JCA、HTTP GET 和 POST 以及套接字;您还可以定义自定义 WSIF 绑定,并可以使用几乎 BPEL 中的任何资源。 该方法使 BPEL 对 EAI 和 B2B 都非常有用。 企业信息系统通常由许多不同的软件部分组成,如可以通过 JCA、EJB 访问的原有应用程序、在不同平台上开发的 Web 服务等。 要集成所有这些东西,必须使用不同的协议。 例如,如果软件移植到不同的服务器,或已升级为使用一种新技术,则必须升级集成代码,除非使用 WSIF。 WSIF 还提供其他重要好处:
首先,我们将重点介绍如何使用 Java 类代替图书等级 Web 服务。 要替换该 Web 服务,您需要创建一个与该 Web 服务具有相同接口的 Java 类;这将需要基于 WSDL 协定开发一个 Java 类。 另一种可能是使 WSDL 适应现有的 Java 类(或其他资源,如 EJB)。 第一种方法更合适,因为它是所谓的协定优先方法。 这样,服务的接口将适应 BPEL 流程的需要,而不是反过来。 Java 到 XML 的绑定 要从 BPEL 中调用 Java 资源,您需要使用 BPEL 变量中的数据,这些变量以输入参数的形式发送到 Java 资源并从 Java 中将数据返回给 BPEL。 BPEL 变量是 XML,而 Java 变量却不是;因此,您需要在 XML 和 Java 之间建立映射。 要从 Java 中处理 XML 数据,有多种方法可供选择:
XML Fa ades。 XML fa ades 是 Oracle BPEL 流程管理器提供的用于 WSIF 的原始 Java 到 XML 的绑定,并且是该产品的有机组成部分。 XML fa ades 是一组 Java 接口和类。通过这些接口和类,您可以以相对简单的方式使用 get/set 方法访问和修改 BPEL 变量中存储的 XML 数据。 这种方式不要求您直接操作 XML — 此外,XML 隐藏在 fa ade 之后,您可以通过常规 Java 接口操作数据(一个称作 XML 串行化的概念)。 XML fa ades 的设计思想是通过与内置类型的映射为基本数据类型提供支持并从 XML 模式中为复杂类型生成 Java 类。
以下显示了 XML 模式和 Java 类型之间基本数据类型的自动映射:
您可以看到,可以将大多数简单类型映射到基元类型或对象类型。 这样的映射很有用,它可以使映射适应 Java 代码中所用的实际类型。 除简单类型外,您还需要一种映射复杂类型的方法 — 无论是 WSDL 的 <types> 部分中定义的类型还是外部 XML 模式 (XSD) 文件中定义的类型。 例如,在图书等级 Web 服务 WSDL 中,您将看到一个将 BookDscType 类型的 BookRatingRequestMessage 作为输入的操作。 BookDscType 复杂 XML 类型用于 BookRatingRequestMessage 和相应的 BookRatingRequest BPEL 变量:
<xs:schema elementFormDefault="qualified"
targetNamespace="http://oracle.com/service/bookrating/">
<xs:complexType name="BookDscType">
<xs:sequence>
<xs:element name="Title" type="xs:string" />
<xs:element name="ISSN" type="xs:string" />
<xs:element name="Publisher" type="xs:string" />
<xs:element name="Authors" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
针对这个复杂 XML 类型的 XML fa?ade 提供了一个接口和一个类。通过它们您可以使用 Java getter 方法访问各个元素(title、ISSN、publisher、authors)。 XML fa?ade 还允许您使用 setter 方法修改元素数据。
该变量的 XML fa?ade 由提供以下方法的接口 (IBookDscType) 和类 (BookDscType) 组成:
Oracle BPEL 流程管理器提供了一个称作 schemac 的模式编译器实用程序。 使用此实用程序,您可以生成 XML fa?ades。 要为 BookRating.wsdl 生成 XML fa?ade,使用以下命令行:
Z:\WSIF\2_JavaBindingClass>schemac BookRating.wsdl
----------------------------------------------------
Oracle XML Schema Processor Version 10.1.2.0.0
http://otn.oracle.com/bpel
Copyright (c) 2002-2004 - Oracle
(type schemac -help for help)
----------------------------------------------------
schemac> parsing schema file 'BookRating.wsdl' ...
schemac> Loaded schemas from wsdl located at BookRating.wsdl
schemac> generating XML business document ...
schemac> compiling XML business documents ...
Schemac completed successfully.
Z:\WSIF\2_JavaBindingClass>
要从 Java 资源中使用这些类,需要将它们编译到以下目录(BPEL 服务器可以在该目录中访问它们)。
C:\OraBPELPM_1\integration\orabpel\system\classes schemac 实用程序有几个选项。 可以使用 -d 开关定义存储生成的 fa?ade 类的目录。 要查看 fa?ade 源代码,使用 -trace 选项。 schemac 实用程序还可以用于在 Java 类的外部生成 XML 模式。 这对于使服务接口适应现有的 Java 资源很有用。 必须使用 -R 开关并提供不带扩展名的 Java 类名。 开发 Java 类。 要用 Java 类替换图书等级 Web 服务而不修改 BPEL,需要一个与原始的图书等级 Web 服务具有相同接口(协定)的 Java 类。 这意味着 Java 类必须提供具有相同功能的操作,并且这些操作必须接受相同的参数并返回相同的结果类型 - 但操作名不必相同。 看看原始 WSDL 您将发现,图书等级 Web 服务提供了一个名为 BookRating 的操作,该操作接受一个输入消息并提供一个输出消息,因此是同步的:
<portType name="BookRatingPT">
<operation name="BookRating">
<input message="tns:BookRatingRequestMessage" />
<output message="tns:BookRatingResponseMessage" />
</operation>
</portType>
The signatures of both messages are as follows:
<message name="BookRatingRequestMessage">
<part name="book" type="tns:BookDscType" />
</message>
<message name="BookRatingResponseMessage">
<part name="rating" type="xs:int" />
</message>
该操作的输入参数的类型为 BookDscType。 要将 BookDscType 映射到 Java,使用相应的 XML fa?ade,即您在前面使用 schemac 工具生成的 XML fa?ade。 该操作的返回类型为 BookRatingResponseMessage 消息,其类型为 xs:int。 xs:int 类型映射 java.lang.Integer。 (它还可以映射到 int 或 java.math.BigInteger,但您在此处使用 java.lang.Integer。)
您现在就准备好为图书等级 Web 服务编写 Java 等价类了。 调用新的 Java 类 BookRatingJava,该类将包含一个名为 getBookRating 的方法。 该方法的主体将超简单 - 您将向服务器控制台打印一个通知并返回等级 4。(例如,在实际例子中,您可以根据数据库中的数据计算图书等级。) 此代码如下所示。 注意如何使用 getTitle() 和 getISSN() 方法分别访问图书标题和 ISSN: package com.oracle.rating;
import com.oracle.service.bookrating.*;
public class BookRatingJava {
public Integer getBookRating (BookDscType book) {
System.out.println("Book rating for "+book.getTitle()+" ("+book.getISSN()+"): 4.");
return new Integer(4);
}
}
在此处添加控制台输出是为了确认该流程实际上调用了 Java 类而非 Web 服务。
在 WSDL 中定义 WSIF 绑定。要“说服”BPEL 流程用 Java 类代替 Web 服务,必须定义到 Java 类的 WSIF 绑定。 您将在图书等级 WSDL(您将在其中添加绑定部分)中执行此操作。 每个 WSIF 绑定由两部分组成。 首先,必须定义实际绑定,其中您将指定:
在实际情况中,某个资源(如 Java 类或 EJB)可能没有 WSDL。 此时必须执行以下步骤:
针对 Java 类的 WSIF 绑定。 下面我们将为图书等级 Java 类定义 WSIF 绑定。 首先在 WSDL 文档的根元素( <definitions> 标记)中定义两个由 WSIF 提供程序使用的命名空间。 格式命名空间用于定义类型映射,java 命名空间用于定义操作映射以及 Java 类的全名:
<?xml version="1.0" encoding="utf-8" ?>
<definitions xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://oracle.com/service/bookrating/"
targetNamespace="http://oracle.com/service/bookrating/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/"
xmlns:format="http://schemas.xmlsoap.org/wsdl/formatbinding/"
xmlns:java="http://schemas.xmlsoap.org/wsdl/java/" >
...
接下来,添加绑定部分。 该部分通常位于端口类型声明之后、合作伙伴链接类型之前。 下面为 BookRatingPT 端口类型定义 Java 绑定:
...
<service name="BookRating">
<port name="JavaPort" binding="tns:JavaBinding">
<java:address className="com.oracle.rating.BookRatingJava"/>
</port>
</service>
图书等级 WSDL 的其他部分(包括合作伙伴链接类型)未更改。
测试该示例。 您现在就可以测试该示例并确认 BPEL 流程将使用 Java 类代替原始的 Web 服务了。 注意,您只修改了 WSDL;您并未对 BPEL 流程代码进行任何更改。 您将使用原始的 BPEL 代码和同一合作伙伴链接,并使用通常用于调用 Web 服务的 <invoke> 活动调用 BookRatingJava Java 类。 再次调用 BPEL 代码以调用图书等级服务:
...
<!-- Synchronously invoke the Book Rating Web Service -->
<scope name="BookRatingInvoke">
<faultHandlers>
<catchAll>
<!-- If book rating is not available assign 0 -->
<assign>
<copy>
<from expression="number(0)"/>
<to variable="BookRatingResponse" part="rating"/>
</copy>
</assign>
</catchAll>
</faultHandlers>
在测试该示例之前,必须执行几个“簿记”活动。 首先,必须确保 BPEL 流程将使用已修改的 WSDL。 为此,修改 bpel.xml 文件,指定应从当前目录而非 Web 服务本身中提取 BookRating.wsdl 文件:
<?xml version="1.0" encoding="UTF-8" ?>
<BPELSuitcase>
<BPELProcess src="BuyBook.bpel" id="BuyBookJavaBinding">
<partnerLinkBindings>
<partnerLinkBinding name="Client">
<property name="wsdlLocation">
BuyBook.wsdl
</property>
</partnerLinkBinding>
然后,使用 schemac 实用程序生成 XML fa?ade 并编译 BookRatingJava 类。 必须将 XML fa?ade 和 Java 类部署到 C:\OraBPELPM_1\integration\bpelpm\orabpel\system\classes 目录,BPEL 服务器可以在该目录中找到并使用它们。 最简单的方法是修改 build.xml。build.xml 应调用 scemac 编译器、 javac 编译器和 bpelc 编译器:
<?xml version="1.0"?>
<project name="BuyBookJavaBinding" default="all" basedir=".">
<property name="deploy" value="default"/>
<property name="rev" value="1.0"/>
启动 obant 实用程序后,将获得以下输出:
Z:\WSIF\2_JavaBindingClass>obant
Z:\WSIF\2_JavaBindingClass>SETLOCAL
Buildfile:build.xml
CompileJava:
[schemac] schemac> parsing schema file 'Z:\WSIF\2_JavaBindingClass/BookRating.
wsdl' ...
[schemac] schemac> Loaded schemas from wsdl located at Z:\WSIF\2_JavaBindingCl
ass/BookRating.wsdl
[schemac] schemac> generating XML business document ...
[schemac] schemac> compiling XML business documents ...
[javac] Compiling 1 source file to C:\OraBPELPM_1\integration\orabpel\system
\classes
main:
[bpelc] validating "Z:\WSIF\2_JavaBindingClass\BuyBook.bpel" ...
[bpelc] BPEL suitcase deployed to: C:\OraBPELPM_1\integration\orabpel\domain
s\default\deploy
all:
BUILD SUCCESSFUL
Total time: 17 seconds
Z:\WSIF\2_JavaBindingClass>ENDLOCAL
Z:\WSIF\2_JavaBindingClass>
然后,使用 BPEL 控制台启动该流程。 在可视化流窗口中,可以观察该流程的执行情况。 注意,BPEL 中已经使用了 <invoke> 活动,且图书等级为 4,而原始图书等级 Web 服务返回 5:
为了绝对确保 BPEL 流程管理器已经调用了 Java 类,BPEL 流程管理器控制台窗口将显示以下输出:
05/10/19 19:35:36 Book rating for Business Process Execution Language (1-904811-
18-3): 4.
异常处理
从 BPEL 中调用 Java 资源时,我们需要通过某种方法将 Java 异常传送给 BPEL。 通过 WSIF,可以将 Java 异常映射为 WSDL 故障并使用 BPEL 故障处理程序处理它们。 异常串行化程序负责映射。 Oracle BPEL 流程管理器提供了一个默认的异常串行化程序,您也可以编写自己的自定义串行化程序。 为演示如何将 Java 异常传送给 BPEL,我们将扩展该示例。 首先,使用默认序列化程序,然后使用自定义串行化程序扩展该示例。 执行以下步骤:
package com.oracle.rating;
public class BookDoesNotExistException extends Exception
{
String detailDesc;
String bookTitle;
public BookDoesNotExistException(String message, String detailDesc, String bookTitle)
{
super(message);
this.detailDesc = detailDesc;
this.bookTitle = bookTitle;
}
public String getDetailDesc()
{
return detailDesc;
}
public String getBookTitle()
{
return bookTitle;
}
}
抛出 Java 异常。 然后,修改 BookRatingJava Java 类。 如果图书的 ISSN 等于 999,则将抛出异常:
package com.oracle.rating;
import com.oracle.service.bookrating.*;
public class BookRatingJavaUserException {
public Integer getBookRating (BookDscType book) throws BookDoesNotExistException {
if
在 WSDL 中定义故障。 在下个步骤中,您将在 WSDL 中定义相应的故障。 将把 Java 异常传送给此故障。 由于您将使用默认的异常串行化程序,因此必须使用一个包含以下两个元素的特定复杂类型: faultstring 和 detail。 您将把该复杂类型添加到图书等级 WSDL 的 <types> 部分:
<xs:complexType name="BookDoesNotExistExceptionType">
<xs:sequence>
<xs:element name="faultstring" type="xs:string" />
<xs:element name="detail" type="xs:string" />
</xs:sequence>
</xs:complexType>
然后,定义相应的消息:
<message name="BookDoesNotExistException">
<part name="exception" type="tns:BookDoesNotExistExceptionType" />
</message>
最后,将故障消息添加到 BookRating 操作签名:
<portType name="BookRatingPT">
<operation name="BookRating">
<input message="tns:BookRatingRequestMessage" />
<output message="tns:BookRatingResponseMessage" />
默认的异常串行化程序将创建 fault 元素并使用 Exception.getMessage() 返回的内容填充 faultstring,使用 Exception.toString() 返回的内容填充 detail 元素。
为异常定义 WSIF 绑定。 现在,就可以将异常添加到 WSIF 绑定了。 必须为 BookDoesNotExistExceptionType XML 类型定义类型映射,在本文的示例中,该类型将映射为相应的 Java 异常类,即 com.oracle.rating.BookDoesNotExistException。 还必须将故障消息名 ( BookDoesNotExistException) 添加到操作映射部分:
<binding name="JavaBinding" type="tns:BookRatingPT">
<java:binding/>
<format:typeMapping encoding="Java" style="Java">
<format:typeMap typeName="tns:BookDscType"
formatType="com.oracle.service.bookrating.BookDscType" />
要使该示例可以正常运行,必须编译 Java 类并将它们部署到 C:\OraBPELPM_1\integration\orabpel\system\classes 目录(BPEL 服务器可以在该目录中访问它们)。 最简单的方法是对该示例使用 obant 实用程序:
Z:\WSIF\3_JavaBindingUserExceptionDefaultSerializer>obant
Z:\WSIF\3_JavaBindingUserExceptionDefaultSerializer>SETLOCAL
Buildfile:build.xml
CompileJava:
[schemac] schemac> parsing schema file 'Z:\WSIF\3_JavaBindingUserExceptionDefa
ultSerializer/BookRating.wsdl' ...
[schemac] schemac> Loaded schemas from wsdl located at Z:\WSIF\3_JavaBindingUs
erExceptionDefaultSerializer/BookRating.wsdl
[schemac] schemac> generating XML business document ...
[schemac] schemac> compiling XML business documents ...
[javac] Compiling 2 source files to C:\OraBPELPM_1\integration\orabpel\syste
m\classes
main:
[bpelc] validating "Z:\WSIF\3_JavaBindingUserExceptionDefaultSerializer\BuyB
ook.bpel" ...
[bpelc] BPEL suitcase deployed to: C:\OraBPELPM_1\integration\orabpel\domain
s\default\deploy
all:
BUILD SUCCESSFUL
Total time: 18 seconds
Z:\WSIF\3_JavaBindingUserExceptionDefaultSerializer>ENDLOCAL
Z:\WSIF\3_JavaBindingUserExceptionDefaultSerializer>
从 BPEL 控制台启动该示例并输入 ISSN 999 后,您将获得以下输出:
自定义异常串行化程序。 如果对 WSDL 故障的结构(由 faultstring 和 detail 元素组成)不满意,并希望对 Java 异常到 WSDL 故障的映射进行更多的控制,可以使用自定义异常串行化程序。 自定义异常串行化程序是一个 Java 类,用于将异常及其属性映射为用于 WSDL 故障的复杂类型。 要了解如何开发自定义串行化程序,执行以下步骤:
<xs:complexType name="BookDoesNotExistExceptionType">
<xs:sequence>
<xs:element name="message" type="xs:string" />
<xs:element name="detailDesc" type="xs:string" />
<xs:element name="bookTitle" type="xs:string" />
</xs:sequence>
</xs:complexType>
自定义异常串行化程序是一个 Java 类,它定义了 Java 异常如何映射为 WSDL 故障复杂类型。 异常串行化程序必须将 Java 异常属性映射为异常消息的相应 XML 元素并必须实现以下接口:
public interface IExceptionSerializer {
public Element serialize(Throwable ex,
String messageName,
String namespaceURI);
}
对于该示例,您将把自定义异常串行化程序命名为 BookDoesNotExistExceptionSerializer 并扩展现有的 ExceptionSerializer 类。 使用 DOM API,我们将把 Java 异常的三个属性(消息、详细描述、书名)映射为上面提供的 XML 模式类型 ( BookDoesNotExistExceptionType):
package com.oracle.rating;
import org.w3c.dom.Element;
import com.collaxa.xml.XMLHelper;
import com.oracle.bpel.xml.util.ExceptionSerializer;
import com.oracle.bpel.xml.util.IExceptionSerializer;
public class BookDoesNotExistExceptionSerializer extends ExceptionSerializer
implements IExceptionSerializer {
public Element serialize(Throwable ex, String messageName, String namespaceURI) {
if(ex instanceof BookDoesNotExistException)
{
BookDoesNotExistException brEx = (BookDoesNotExistException)ex;
Element exceptionElement =
XMLHelper.createRootElement(messageName, namespaceURI,"tns");
Element messageElement =
XMLHelper.createElement("message","tns",namespaceURI);
messageElement.setNodeValue(brEx.getMessage());
exceptionElement.appendChild(messageElement);
Element detailElement =
XMLHelper.createElement("detailDesc","tns",namespaceURI);
detailElement.setNodeValue(brEx.getDetailDesc());
exceptionElement.appendChild(detailElement);
Element bookElement =
XMLHelper.createElement("bookTitle","tns",namespaceURI);
bookElement.setNodeValue(brEx.getBookTitle());
exceptionElement.appendChild(bookElement);
return exceptionElement;
}
return super.serialize(ex, messageName, namespaceURI);
}
}
最后一步是在 Oracle BPEL 流程管理器中注册自定义异常串行化程序。 该步骤将指示 BPEL 流程管理器用您的自定义串行化程序代替默认的串行化程序。 为此,在 bpel.xml 部署描述符中定义 exceptionSerializer 属性:
<partnerLinkBinding name="BookRating">
<property name="wsdlLocation">
BookRating.wsdl
</property>
与前一个示例一样,必须编译 Java 类并将它们部署到 C:\OraBPELPM_1\integration\orabpel\system\classes 目录。 使用 obant 实用程序:
Z:\WSIF\3_JavaBindingUserExceptionCustomSerializer>obant
Z:\WSIF\3_JavaBindingUserExceptionCustomSerializer>SETLOCAL
Buildfile:build.xml
CompileJava:
[schemac] schemac> parsing schema file 'Z:\WSIF\3_JavaBindingUserExceptionCust
omSerializer/BookRating.wsdl' ...
[schemac] schemac> Loaded schemas from wsdl located at Z:\WSIF\3_JavaBindingUs
erExceptionCustomSerializer/BookRating.wsdl
[schemac] schemac> generating XML business document ...
[schemac] schemac> compiling XML business documents ...
[javac] Compiling 3 source files to C:\OraBPELPM_1\integration\orabpel\syste
m\classes
main:
[bpelc] validating "Z:\WSIF\3_JavaBindingUserExceptionCustomSerializer\BuyBo
ok.bpel" ...
[bpelc] BPEL suitcase deployed to: C:\OraBPELPM_1\integration\orabpel\domain
s\default\deploy
all:
BUILD SUCCESSFUL
Total time: 21 seconds
Z:\WSIF\3_JavaBindingUserExceptionCustomSerializer>ENDLOCAL
Z:\WSIF\3_JavaBindingUserExceptionCustomSerializer>
从 BPEL 控制台启动该示例并输入 ISSN 999 后,您将获得以下输出: 注意不同的故障结构:
自定义 Java 串行化程序。 自定义 Java 串行化程序是一个实现 IJavaSerializer 接口的类。 它必须提供以下两个方法的实现: serialize 和 deserialize。
public interface IJavaSerializer {
public Element serialize(Object obj, Class type, String name, String namespaceURI,
String prefix, Map classMap) throws Exception;
public Object deserialize(Element el, Class type) throws Exception;
}
与自定义异常串行化程序相似,必须将编译后的类部署到 C:\OraBPELPM_1\integration\orabpel\system\classes 目录,并在 bpel.xml 部署描述符中定义 javaSerializer 属性:
<partnerLinkBinding name="helper">
<property name="wsdlLocation">HelperService.wsdl</property>
Oracle 提供了三个现成的自定义串行化程序: Java API for XML Bindings (JAXB)、XML Bean 和 Axis Bean。
JAXB 是 Java Web Services Developer Pack 的一部分,并提供了一个在概念上与 XML fa?ade 相似的方法,但在几个细节方面存在差异。 要将 JAXB 串行化与 Oracle BPEL 流程管理器结合使用,执行以下步骤:
<partnerLinkBinding name="helper">
<property name="wsdlLocation">HelperService.wsdl</property>
XML Bean 是 Java 到 XML 绑定的另一种方法,最先由 BEA(它将该项目捐赠给 Apache 社区)开发。 与 XML fa?ades 和 JAXB 不同,XML Bean 提供了一个并不对 Java 开发人员完全隐藏 XML 的方法。 相反,它为 Java 接口提供了 getter/setter 方法以及其他方法(带 x 后缀),您可以在需要时通过它们直接操作 XML。 XML Bean 还可以识别 XML Infoset - 当将 XML 转换为 Java 对象时,开发人员可以使用整个 XML Infoset。
与 JAXB 相似,必须执行几个配置步骤才能使用 XML Bean:
<partnerLinkBinding name="xmlBeansService">
<property name="wsdlLocation">XMLBeansService.wsdl</property>
第三个用于 Java 到 XML 绑定的著名方法是 Axis Bean。您同样可以将它们用于 Oracle BPEL 流程管理器。
与前两个示例相似,必须执行几个配置步骤才能使用 Axis Bean:
<partnerLinkBinding name="AxisBeansService">
<property name="wsdlLocation">AxisBeansService.wsdl</property>
用于 EJB 的 WSIF 绑定
现在,您知道了如何通过 WSIF 绑定使用 Java 类代替 Web 服务。 同样,您可以使用 EJB,尤其是无状态会话 bean。 为演示 WSIF EJB 绑定,我们将扩展该示例。 您将在 BPEL 流程中增加一个活动;在调用图书等级服务后,将调用出版商等级服务。 通过 WSIF 绑定,您将使用会话 bean 代替 Web 服务。 假设此会话 bean 已经存在。 为实现此目的,您将执行几个步骤:
package com.oracle.ratingSB;
import java.rmi.RemoteException;
import javax.ejb.EJBObject;
public interface PubRating extends EJBObject
{
public int getAvgPubRating (String name) throws RemoteException;
}
您可以看到,它提供了一个名为 getAvgPubRating 的方法,该方法接受一个字符串作为输入并返回一个整数。 在此,您将不显示主接口、实现类以及部署描述符(参见示例代码)。
现在定义相应的 WSDL 文档。该文档非常简单,它定义了两个消息( PubRatingRequestMessage 和 PubRatingResponseMessage)。 它们在操作 PubRating 中分别用作输入和输出。 该操作在 PubRatingPT 端口类型中声明:
<?xml version="1.0"?>
<definitions xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://oracle.com/service/pubrating/"
targetNamespace="http://oracle.com/service/pubrating/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/"
xmlns:format="http://schemas.xmlsoap.org/wsdl/formatbinding/"
xmlns:ejb="http://schemas.xmlsoap.org/wsdl/ejb/" >
<message name="PubRatingRequestMessage">
<part name="name" type="xs:string" />
</message>
<message name="PubRatingResponseMessage">
<part name="rating" type="xs:int" />
</message>
<portType name="PubRatingPT">
<operation name="PubRating">
<input name="PubRatingRequest" message="tns:PubRatingRequestMessage" />
<output name="PubRatingResponse" message="tns:PubRatingResponseMessage" />
</operation>
</portType>
</definitions>
添加合作伙伴链接类型。 要使用 WSDL,必须添加合作伙伴链接类型。 该操作是同步的;因此,您只需要一个角色:
<plnk:partnerLinkType name="PubRatingLT">
<plnk:role name="PubRatingService">
<plnk:portType name="tns:PubRatingPT" />
</plnk:role>
</plnk:partnerLinkType>
补充 BPEL 流程。 现在,您准备好补充 BPEL 流程来调用出版商等级服务了。 首先,定义一个新的合作伙伴链接:
<partnerLink name="PubRating"
partnerLinkType="pbr:PubRatingLT"
partnerRole="PubRatingService"/>
然后,将与出版商等级服务的交互作为一个新的作用域添加到图书等级作用域之后。 请注意,您在此只向 BPEL 中添加新功能:
<scope name="RetrievePublisherRating">
<variables>
<variable name="PubRatingRequest" messageType="pbr:PubRatingRequestMessage"/>
<variable name="PubRatingResponse" messageType="pbr:PubRatingResponseMessage"/>
</variables>
<faultHandlers>
<catchAll>
<sequence>
<assign>
<copy>
<from expression="string('Unable to retrieve publisher rating')" />
<to variable="Fault" part="error" />
</copy>
</assign>
<invoke partnerLink="Client"
portType="buy:ClientCallbackPT"
operation="ClientCallbackFault"
inputVariable="Fault" />
</sequence>
</catchAll>
</faultHandlers>
<sequence>
<assign>
<copy>
<from variable="BookPurchase" part="book" query="/book/bkr:Publisher"/>
<to variable="PubRatingRequest" part="name"/>
</copy>
</assign>
<invoke partnerLink="PubRating"
portType="pbr:PubRatingPT"
operation="PubRating"
inputVariable="PubRatingRequest"
outputVariable="PubRatingResponse" />
</sequence>
</scope>
添加用于 EJB 的 WSIF 绑定。 WSIF EJB 绑定类似于 Java 类绑定,它们主要的差别在于您必须指定与 WSDL 操作到 EJB 方法的映射相关的细节。
下面显示了出版商等级服务 WSDL 文件中的 WSIF EJB 绑定片段。 您首先定义了类型映射,然后指定了要用于 PubRating 操作的方法 ( getAvgPubRating())。 请注意,您已经为参数 ( name) 和返回 ( rating) 指定了消息部分名称。 您还指定了输入和输出消息名(分别为 PubRatingRequest 和 PubRatingResponse):
<binding name="EJBBinding" type="tns:PubRatingPT">
<ejb:binding/>
<format:typeMapping encoding="Java" style="Java">
<format:typeMap typeName="xs:string" formatType="java.lang.String" />
<format:typeMap typeName="xs:int" formatType="int" />
</format:typeMapping>
<operation name="PubRating">
<ejb:operation
methodName="getAvgPubRating"
parameterOrder="name"
interface="remote"
returnPart="rating" />
<input name="PubRatingRequest"/>
<output name="PubRatingResponse"/>
</operation>
</binding>
在服务绑定中,必须指定 EJB 的其他详细信息,如 JNDI 名、JNDI 提供程序 URL 以及初始语境工厂。 JNDI 提供程序 URL 对每个部署都是特定的。 在本示例中为 ormi://localhost/SessionBean。 可以使用 obant 实用程序在部署时将 [jndiProviderURL] 替换为实际地址(有关详细信息,请查看 build.xml 文件):
<service name="PubRatingPT">
<port name="EJBPort" binding="tns:EJBBinding">
<ejb:address className="com.oracle.ratingSB.PubRatingHome"
jndiName="ejb/session/PubRating"
initialContextFactory="com.evermind.server.rmi.RMIInitialContextFactory"
jndiProviderURL="[jndiProviderURL]"/>
</port>
</service>
现在,您基本上准备好部署该示例并对它进行测试了。 别忘了将 wsdlLocation 属性添加到 bpel.xml 部署描述符:
<partnerLinkBinding name="PubRating">
<property name="wsdlLocation">PubRatingBinded.wsdl</property>
</partnerLinkBinding>
请注意,可以使用此部署描述符添加 EJB 所需的其他属性,如如果 EJB 需要身份验证和授权,则添加 java.naming.security.principal 和 java.naming.security.credentials:
<partnerLinkBinding name="PubRating">
<property name="wsdlLocation">PubRatingBinded.wsdl</property>
要测试该示例,首先必须部署会话 bean,然后部署 BPEL 流程。 再次使用 obant,它将自动执行该过程:
Z:\WSIF\4_JavaBindingEJB>obant
Z:\WSIF\4_JavaBindingEJB>SETLOCAL
Buildfile:build.xml
deploySessionBean:
build_ear:
deployIas:
deployOc4j:
[java] Notification ==> Application Deployer for SessionBean STARTS [ 2005-
10-19T19:47:00.891CEST ]
[java] Notification ==> Undeploy previous deployment
[java] Notification ==> Copy the archive to C:\OraBPELPM_1\integration\orab
pel\system\appserver\oc4j\j2ee\home\applications\SessionBean.ear
[java] Notification ==> Unpack SessionBean.ear begins...
[java] Notification ==> Unpack SessionBean.ear ends...
[java] Notification ==> Initialize SessionBean.ear begins...
[java] Notification ==> Initialize SessionBean.ear ends...
[java] Notification ==> Application Deployer for SessionBean COMPLETES [ 20
05-10-19T19:47:19.470CEST ]
bindingWsdl:
[copy] Copying 1 file to Z:\WSIF\4_JavaBindingEJB
setJndiUrlOrclej2ee:
setJndiUrlIas:
setJndiUrlOc4j:
[echo] Replacing token [jndiProviderURL] by ormi://virtualxp/SessionBean in
Z:\WSIF\4_JavaBindingEJB/PubRatingBinded.wsdl
main:
[bpelc] validating "Z:\WSIF\4_JavaBindingEJB\BuyBook.bpel" ...
[bpelc] BPEL suitcase deployed to: C:\OraBPELPM_1\integration\orabpel\domain
s\default\deploy
all:
BUILD SUCCESSFUL
Total time: 28 seconds
Z:\WSIF\4_JavaBindingEJB>ENDLOCAL
Z:\WSIF\4_JavaBindingEJB>
从控制台中启动 BPEL 流程后,您将看到已经调用了出版商等级服务:
要绝对确保已经调用了 EJB,请查看 BPEL 服务器控制台窗口;您应看到以下输出:
05/10/19 19:50:51 Tutalii: C:\OraBPELPM_1\integration\orabpel\lib\orabpel.jar ar
chive
05/10/19 19:50:54 Avg. publisher rating for Packt Publishing: 5.
从 JDeveloper 中生成 WSIF 绑定
手动编写 WSIF 绑定会非常复杂;因此,Oracle JDeveloper 10.1.3(编写本文时的早期试用版中提供)提供了一个为现有 Java 资源(如 Java 类和 EJB)自动生成 WSDL 和 WSIF 的向导。 这显著降低了从 BPEL 中调用 Java 资源的工作量并使 BPEL 更适用于集成。 如果基于 Java 类或 EJB,则必须启动该向导来创建 Java Web 服务。 以下屏幕截图适用于 Java 类示例:
选择符合 Java EE 1.4 的 JAX-RPC Web 服务类型。
然后,选择要使用的 Java 类或无状态会话 bean。 选中 WSIF 绑定选项(以生成 WSIF 绑定)。
然后,选择 SOAP 消息格式,您可以在其中使用 Document/Wrapped、Document/Literal、RPC/Literal 或 RPC/Encoded 表示形式。
然后,在 XML 类型以及它们的 Java 等价类和相应的串行化程序之间指定自定义映射。
指定 Web 服务使用的命名空间。
最后,选择应通过 WSDL 公开的方法:
该向导提供了其他步骤,您可以在这些步骤中指定可选的类加载程序、JAX-RPC 处理程序类、服务状态(有状态)以及服务使用的其他类。 大多数情况下,您不必指定它们,因此可以按 Finish 按钮完成该向导,并查看所生成的 WSDL,其中您将找到与手动编写的 WSIF 绑定类似的 WSIF 绑定。 有关该向导的详细信息,请参考 JDeveloper 文档。 结论 您已经在本文提供的各个示例中了解到,WSIF 提供了类似 EAI 的功能以及以简单、灵活的方式配置 BPEL 流程的合作伙伴服务的灵活性。 显而易见,WSIF 将 BPEL 的可用范围扩展到现有资源并使 BPEL 成为一种对 SOA 而言更为重要的技术。
将您的意见发送给我们 |