1、Jboss ESB的简介 一、 什么是ESB。 ESB的全称是Enterprise Service Bus,即企业服务总线。ESB是过去消息中间件的发展,ESB采用了“总线”这样一种模式来管理和简化应用之间的集成拓扑结构,以广为接受的开放标准为基础来支持应用之间在消息、事件和服务的级别上动态的互连互通。 ESB是一种在松散耦合的服务和应用之间标准的集成方式。它能够做用于: ①面向服务的架构 - 分布式的应用由可重用的服务组成。 ②面向消息的架构 - 应用之间经过ESB发送和接受消息。java
③事件驱动的架构 - 应用之间异步地产生和接收消息。 用一句比较通俗的话来描述ESB:ESB就是在SOA架构中实现服务间智能化集成与管理的中介。 二、 ESB和SOA之间的关系。 介绍ESB就不得不提到SOA的概念,那么什么是SOA呐? 简单的说,SOA(service-oriented architecture)是面向服务的体系结构,是一类分布式系统的体系结构。这类系统是将异构平台上应用程序的不一样功能部件(称为服务)经过这些服务之间定义良好的接口和规范按松耦合方式整合在一块儿,即将多个现有的应用软件经过网络将其整合成一个新系统。 多应用的整合不可是跨平台的,并且应该是松耦合的,也就是说,被整合的应用自身仍保持其自主,如香港政府已回归中国,但保持一国二制。 新增设的业务功能,应容许适应变化,即随需应变。 如何作到跨平台、松耦合,除使用方和服务方外,另有中介方,提供驻册登记和查询。如今社会的劳务市场和职业介绍所等都起这样做用。即先查询、梆定、而后调用。 在SOA的体系结构中,简单的能够分为以下几个角色: ①服务使用者:服务使用者是一个应用程序、一个软件模块或须要一个服务的另外一个服务。它发起对注册中心中的服务的查询,经过传输绑定服务,而且执行服务功能。服务使用者根据接口契约来执行服务。web
②服务提供者:服务提供者是一个可经过网络寻址的实体,它接受和执行来自使用者的请求。它将本身的服务和接口契约发布到服务注册中心,以便服务使用者能够发现和访问该服务。 ③服务注册中心:服务注册中心是服务发现的支持者。它包含一个可用服务的存储库,并容许感兴趣的服务使用者查找服务提供者接口。 SOA体系结构中的操做 ①发布:为了使服务可访问,须要发布服务描述以使服务使用者能够发现和调用它。 ②发现:服务请求者定位服务,方法是查询服务注册中心来找到知足其标准的服务。 ③绑定和调用:在检索完服务描述以后,服务使用者继续根据服务描述中的信息来调用服务。 SOA的优势以下: ①利用现有的资产。 方法是将这些现有的资产包装成提供企业功能的服务。组织能够继续从现有的资源中获取价值,而没必要从新从头开始构建。 ②更易于集成和管理复杂性。 将基础设施和实现发生的改变所带来的影响降到最低限度。由于复杂性是隔离的。当更多的企业一块儿协做提供价值链时,这会变得更加剧要。 那么ESB和SOA有什么关系呐? ESB同SOA之间的关系:ESB是逻辑上与SOA 所遵循的基本原则保持一致的服务集成基础架构,它提供了服务管理的方法和在分布式异构环境中进行服务交互的功能。 能够这样说,ESB是特定环境下(SOA架构中)实施EAI的方式:首先,在ESB系统中,被集成的对象被明肯定义为服务,而不是传统EAI中各类各样的中间件平台,这样就极大简化了在集成异构性上的考虑,由于无论有怎样的应用底层实现,只要是SOA架构中的服务,它就必定是基于标准的。 其次,ESB明确强调消息(Message)处理在集成过程当中的做用,这里的消息指的是应用环境中被集成对象之间的沟通。以往传统的EAI实施中碰到的最大的问题就是被集成者都有本身的方言,即各自的消息格式。做为基础架构的EAI系统,必须可以对系统范畴内的任何一种消息进行解析。传统的EAI系统中的消息处理大可能是被动的,消息的处理须要各自中间件的私有方式支持,例如API的方式。所以尽管消息处理自己很重要,但消息的直接处理不会是传统EAI系统的核心。ESB系统因为集成对象统一到服务,消息在应用服务之间传递时格式是标准的,直接面向消息的处理方式成为可能。若是ESB可以在底层支持现有的各类通信协议,那么对消息的处理就彻底不考虑底层的传输细节,而直接经过消息的标准格式定义来进行。这样,在ESB中,对消息的处理就会成为ESB的核心,由于经过消息处理来集成服务是最简单可行的方式。这也是ESB中总线(Bus)功能的体现。其实,总线的概念并不新鲜,传统的EAI系统中,也曾经提出过信息总线的概念,经过某种中间件平台,如CORBA来链接企业信息孤岛,可是,ESB的概念不只仅是提供消息交互的通道,更重要的是提供服务的智能化集成基础架构。 最后,事件驱动成为ESB的重要特征。一般服务之间传递的消息有两种形式,一种是调用(Call),即请求/回应方式,这是常见的同步模式。还有一种咱们称之为单路消息(One-way),它的目的每每是触发异步的事件,发送者不须要立刻获得回复。考虑到有些应用服务是长时间运行的,所以,这种异步服务之间的消息交互也是ESB必须支持的。除此以外,ESB的不少功能均可以利用这种机制来实现,例如,SOA中服务的性能监控等基础架构功能,须要经过ESB来提供数据,当服务的请求经过ESB中转的时候,ESB很容易经过事件驱动机制向SOA的基础架构服务传递信息。 三、 Jboss ESB的主要特征和功能 ①Jboos esb 4.2主要的特性包括: 支持普通的通知框架。支持的Transports包括JMS (JBossMQ, JBoss Messaging, Oracle AQ and MQSeries), email, 数据库或文件系统. 推荐的缺省 JMS 实现是JBoss Messaging 1.2.0GA. jBPM 集成.数据库
支持WS-BPEL. 支持Web Services. 使用特定的ESB 服务器改进部署和配置. 支持Groovy. trailblazer 例子.apache
许多quickstart 例子. 支持使用Smooks or XSLT转数据 . 支持交互步骤松耦合的侦听器和动做模型. 使用Drools或者 XPath 基于内容的路由. 支持JAX-R和jUDDI注册 . 提供容许non-ESB traffic与ESB进行集成的网关. 图形化的配置编辑器. 高性能和可靠性(大型保险公司3年的使用). ②何时使用Jboos ESB 下面的图表说明JBossESB能够被使用的具体例子。虽然这些例子在参与者间使用非互操做的JMS实现特殊的交互,但原理是相同的。 下面的这张图表显示了在两个系统间简单的文件发送,而没有使用消息队列管理。服务器
下一个图表说明了在与上图相同的环境下如何经过注入实现转换。网络
下面的几个例子,咱们使用了消息队列系统(例如,一个JMS实现)。session
下面这幅图表显示了在相同环境下的转换和排队。架构
JBossESB能被用在多种状况下。举一个例子,下面的图显示了ESB利用文件系统进行基本数据转换。app
最后的场景又是一个使用了转换和排队的例子。composer
3. JBossESB的核心 JbossESB创建在三个核心的体系结构组件上: • 消息监听器和消息过滤器代码。消息监听器监听消息(例如,JMS上的Queue/Topic,或文件系统),并路由。而后引导消息处处理管道。消息过滤器则过滤消息,并将消息路由到另外一个消息端点。 • 数据转换使用Smooks转换处理器。 • 一个基于路由服务的目录。 • 一个消息存储库, 用来存储在ESB上交换的消息/事件。
一个典型的JBossESB部署以下图。
2、Jboss ESB的详细介绍。 一、总述 JBossESB是JBoss推出的ESB的实现,也是JBoss的SOA产品的基础.首先你们对于ESB的定义有不少的不一样,我我的更喜欢把ESB看做是系统集成的一个平台. JBossESB是一个基于消息的中间件(Message Oriented). 在这篇文章中,咱们只是看待ESB中的一个很基础部份,也就是怎么从Endpoint A发送信息给ESB的服务S1,而后再有S1发送信息到Endpoint B去调用服务。还有一些关于Router(路由),Data Transformation(数据转换)功能点的介绍,比较基础要详细了解JbossESB的各类功能请详细参考相关的文档。 咱们就假设一个简单的系统集成场景来开始阐述JBossESB的设计和概念。 A系统(Endpoint A) – Message -> ESB -> – Message --> B系统 (Endpoint B) 因此,若是简单的对于JBossESB定义的话,咱们能够定义如下三个概念: Message Listener (接收“inbound” message)
Message Filter (发送 "outbound” message)
Message (消息对象) JBossESB 是一个面向服务(Service Oriented)的架构,因此在ESB内部的要么是一个Service, 要么是一个Message. 这里的Service就是指具备实现业务逻辑的服务,也能够是一个实现路由(Router),或者数据转化(Transformation)的服务. 就拿上面的这个例子,系统A发送一个Message给 ESB的一个服务,咱们假设叫作S1, 那么S1收到Message后,作一些处理,转到S2的服务,S2再把处理后的结果发送给系统B. 这样就实现了A和B之间经过ESB的通讯. System A -> message -> S1 -> S2 ->.... -> message -> System B 那么在ESB内部是怎么去表达一个服务呢?这里引入了EndpointReference的概念,简称EPR. 有了服务以后,服务之间是经过什么样的传输层(好比JMS, FTP, HTTP)来通讯呢? 因此ESB的内部也引入了Courier的API, 来统一抽象传输层. 刚咱们也看到了,ESB的内部无非就是一系列的服务, 可是咱们怎么来保存/注册这些服务的呢? JBossESB是使用jUDDI来注册和保存这些服务元数据的。 二、 JBossESB的几个重要概念 在要了解和运行JBossESB以前,咱们最好了解下JBossESB中比较重要的几个概念。 ①Message (消息) ESB内部所交流/传递的都是消息,因此可见这个消息格式的重要性. 在JBossESB中, 定义了一个Message的对象,它是有如下几个部分构成的。 (1). Header (用来存放From, To, Reply-to等Addressing的信息). (2). Body (存放信息主体) (3). Attachment (用来存放附件等)
(4). Properties (5). Context (主要是存放一些相似事务的信息等)
目前在Body里面通常来讲存放两种格式的数据,一个是串行化数据(Serialized Object ),另一个是XML文件,好比常见 的SOAP的payload. 在ESB中,还有两个定义,一个叫ESB-aware Message, 咱们上面所讲的Message就是ESB-aware Message, 正如名字说讲的,它是属于ESB内部的Message对象. 还有个叫 ESB unaware Message,也就是说他一样也是一个message,好比SOAP Message,可是若是把soap message直接让ESB来处理,是处理不了的,因此呢? 常常的在Listener 监听的端口会有个Adapter (在JBossESB里叫作Gateway)来负责把ESB-unaware message 转成 ESB-aware message。 ②Service (服务) ESB的内部服务是用EPR来映射的. ESB的内部服务能够是任何的一个服务,好比说一个FTP的服务,一个基于文件系统的服务等等, 那么这个时候咱们就须要用EPR来对这个服务进行描述.在EPR这个类里,主要是描述了这个服务的URI,以及所必须的一些元数据. 目前在JBossESB中提供的EPR有: FileEPR,EmailEPR,FTPEPR, HibernateEPR等等. 咱们在注册服务的时候,是将EPR的信息注册到UDDI的容器里, 但不只仅是EPR, 还有一些辅助信息,好比定义服务的category-name, service-name. 这些将在后面继续介绍。 ③Listeners, Gateway Listener的做用是负责监听端口,通常来讲,客户端是发送消息到Listener,而后有Listener把消息传递给ESB, 咱们能够把Listener看作是inbound router. 在JBossESB中,咱们是叫GatewayListener, 它通常来讲作两件事情. 监听Message. ESB-unaware message和 ESB-aware message的互转.
目前ESB支持的Gateway有: JMSGatewayListener, JBossRemotingGatewayListener, FileGatewayListener等等. 在MessageComposer这个类里的compose/decompose方法来负责ESB-unaware信息和ESB-aware信息的转化。
public interface MessageComposer<T> {
/**
* Set the composer's configuration
*/
public void setConfiguration(ConfigTree config) throws ConfigurationException;
/**
* Compose an ESB "aware" message from the supplied message payload.
* Implementations need to construct and populate an ESB Message from the
* messagePayload instance.
*/
public Message compose(T messagePayload) throws MessageDeliverException;
/**
* Decompose an ESB "aware" message, extracting and returning the message payload.
*/
public Object decompose(Message message, T originalInputMessagePayload) throws MessageDeliverException;
} ④Couriers
Courier的做用就是负责传输,正如如下接口所显示: public interface Courier extends DeliverOnlyCourier { Public Boolean deliver(Message message) throwsCourierException,MalformedEPRException; }
目前实现的Transport有:JmsCourier, InVMCourier, HibernateCourier, FileCourier等传输层,在ESB内部是经过EPR来跟Courier进行关联的。 ⑤Actions 在JBossESB中,咱们能够把ActionProcessingPipeline类看做是Message Filter, 每一个Message都会通过 ActionProcessingPipeline的处理. 里面有这么个方法: public boolean process(final Message message) 而actionProcessingPipeline又是由Action (ActionPipelineProcessor)来组成的. 咱们能够把Action当作是Interceptor, 由它来实现具体的业务逻辑,能够是路由,又或者数据转化功能等等. 若是你用JBossESB的话,那么Action是一个很是重要的部分,咱们来看下它所定义的接口。 通常来讲自定义的Action把具体的业务逻辑放在Process的方法里,固然了,你也能够定义相对应的Exception处理方法,经过实现processException.在ESB代码中,自定义的Action能够用继承AbstractActionPipelineProcessor 或者 AbstractActionLifecycle。 ⑥Meta-data and Filters 在有些状况下,你须要一些全局的Interceptor,咱们以前说的Action,能够理解成是每一个service的interceptor,可是若是我须要使用log来记录一个消息在各个service之间传输的日志, 又或者想记录消息进入某个service的时间和退出的时间. 那么在JBoss ESB中就有Filter的概念. 若是你要实现本身的Filter,须要继承InputOputFilter类。
public class InputOutputFilter
{
/**
* Called as the message flows towards the transport.
*/
public Message onOutput (Message msg, Map<String, Object> params) throws CourierException
{
return msg;
}
/**
* Called immediately after the message is received from the transport.
*/
public Message onInput (Message msg, Map<String, Object> params) throws CourierException
{
return msg;
}
} 写完本身的Filter后,你须要在$JBossESB/server/config (e.g. default)/deploy/jbossesb.sar/jbossesb-properties.xml里面增长filter. 须要注意的是,在这里配置的filter是对全部的esb包都起做用,是个全局的变量. onInput方法老是在从传输层获取到Message后,第一步所作的工做;相似的, onOutput是给传输层传递前所作的最后一步工做. 你能够在TwoWayCourierImpl中看到这段代码的调用。 ⑦ServiceInvoker 对于客户端调用来讲,EPR, Courier等都太底层了.因此若是对此进行了封装. 咱们对每一个service加以service-category和service-name的属性. 因此若是你想发送一个ESB的内部Message,你只须要知道目标service的service-category和service-name,而后就能够调用ServiceInvoker来调用服务. 不须要去使用Courier等底层的API, 另外用ServiceInvoker还能够支持fail-over等特性.
public class ServiceInvoker {
public ServiceInvoker(String serviceCategory, String serviceName) throws MessageDeliverException {
this(new Service(serviceCategory, serviceName));
}
public Message deliverSync(Message message, long timeoutMillis) throws MessageDeliverException, RegistryException, FaultMessageException
public void deliverAsync(Message message) throws MessageDeliverException
} 三、 Jboss ESB一个简单示例。 为了更好的来解释JBossESB, 最好的一个方法就是试下JBossESB自带的例子,这里咱们先以helloworld_action的例子来说解.
①安装和运行JBossESB sample 到这里,你已经成功的运行了helloworld_action的例子 1 从JBossESB网站下载 jbossesb-server-4.4.GA.zip 2 解压jbossesb-server-4.4.GA.zip, 假设到/var/local/jbossesb-sever4.4. 下面以$jbossesb来替代. 3 在$jbossesb中,运行 bin/run.sh 来启动ESB server 4 另外打开一个窗口,到$jbossesb/samples/quickstarts/helloworld_actions, 运行: ant deploy 5. 再运行: ant runtest 6. 回到JBoss ESB server的控制台上,应该能够看到如下的输出:. 7. INFO [STDOUT] [Hello World Action]. 8. INFO [STDOUT] 9. &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 10. INFO [STDOUT] Body: Hello World Action 11. INFO [STDOUT] &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 12. INFO [STDOUT] ConsoleNotifier 2008/09/26 06:35:39.643< 13. BEFORE** 14. Hello World Action 15. AFTER** 16. >
②分析helloworld_action例子 <1>在看jboss-esb.xml的配置时候,咱们应该分红两个部份. providers和services. a. providers
首先是<providers>,它是有一系列的<provider>组成, 目前有jms-provider, fs-provider, ftp-provider等等. 而后咱们在provider里面定义这个.esb文件里面service所定义的listener所须要的bus, Bus能够简单理解成消息传送所须要的传输层. 正如如下所显示的,咱们定义了两个Bus,一个是给Gateway的Listener用,另一个是给ESB-aware Message传输所须要的传输层.
<providers>
<jms-provider name="JBossMQ" connection-factory="ConnectionFactory">
<jms-bus busid="quickstartGwChannel">
<jms-message-filter
dest-type="QUEUE"
dest-name="queue/quickstart_helloworld_action_Request"
/>
</jms-bus>
<jms-bus busid="quickstartEsbChannel">
<jms-message-filter
dest-type="QUEUE"
dest-name="queue/B"
/>
</jms-bus>
</jms-provider>
</providers> 虽然在这边写的是JBossMQ, 可是对于JBoss ESB server来讲,是默认使用JBoss Messaging的; 若是是把JBoss ESB安装在JBoss AS 4.x的服务器, 那么就是用JBoss MQ, 由于JBoss AS 4.x默认是使用JBoss MQ.
b. services 第二部份就是定义services的部份, 在这里定义了当前这个esb包所提供的services. 每一个service又是由 <listener> 和 <actions>组成的.
<services>
<service category="HelloWorld_ActionESB"
name="SimpleListener"
description="Hello World" >
<listeners>
<jms-listener name="JMS-Gateway"
busidref="quickstartGwChannel"
is-gateway="true"
/>
<jms-listener name="JMS-ESBListener"
busidref="quickstartEsbChannel"
/>
</listeners>
<actions mep="OneWay">
<action name="action2"
class="org.jboss.soa.esb.actions.SystemPrintln"
/>
<action name="displayAction"
class="org.jboss.soa.esb.samples.quickstart.helloworldaction.MyJMSListenerAction"
process="displayMessage">
<property name="exceptionMethod" value="exceptionHandler"/>
</action>
<action name="playAction"
class="org.jboss.soa.esb.samples.quickstart.helloworldaction.MyJMSListenerAction"
process="playWithMessage">
<property name="exceptionMethod" value="exceptionHandler"/>
</action>
</actions>
</service>
</services> 在listener里,咱们经过 busidref来关联到咱们定义在provider里面的bus. 在这里,咱们定义了两个listener. 其中一个是作为Gateway,只负责从外界获取到JMS的消息,而后转成ESB内部所须要的Message. 而另一个listener是用来这个Message在services内部之间通信的通道. 因此对于每一个service来讲,必定要至少定义一个listener来做为内部Message传输用. 这里的action是对消息(Message)处理的地方. <2> MyJMSListenerAction 正如咱们在上面看到的,咱们在jboss-esb.xml中定义了action,咱们看下MyJMSListenerAction.
public class MyJMSListenerAction extends AbstractActionLifecycle
{
protected ConfigTree _config;
public MyJMSListenerAction(ConfigTree config) { _config = config; }
public Message playWithMessage(Message message) throws Exception {
Body msgBody = message.getBody();
String contents = msgBody.get().toString();
StringBuffer sb = new StringBuffer();
sb.append("\nBEFORE**\n");
sb.append(contents);
sb.append("\nAFTER**\n");
msgBody.add(sb.toString());
return message;
}
} 咱们只是截取其中的一部分来讲明,通常来讲每一个Action都要继承AbstractActionLifecycle类,而后输入/输出参数都必须是ESB的Message. 方法名能够随便定义. 你只须要在jboss-esb.xml的action的process属性中写相对应的方法名就能够. 若是不写,默认是process方法. 这里的ConfigTree是个很重要的属性,咱们很常常的会在Action配置其余的信息,那么 全部的信息均可以经过ConfigTree来获取到.好比说在某个Action中配置静态路由信息等等.也正是因为Action中你能够随意的配置你本身的信息,增长了不少的灵活性和扩展性. <3> esb文件目录结构 咱们先看下部署在server下的.esb包的文件目录,通常是包括如下些东西. /META-INF/jboss-esb.xml /META-INF/deployment.xml 在这里定义对其余包或者服务的依赖,或者配置classloader. jbm-queue-service.xml (optional) 这里是定义启动所须要的Queue **.jar (optional) 放些所须要的第三方包
所须要的些classes文件 三、客户端调用服务 目前在JBossESB中,通常有两种方式来调用service. 一种是经过Gateway listener, 另一种是直接经过ServiceInvoker的API来调用. ①经过Gateway来调用服务 回到咱们的例子,咱们经过JMS Gateway来访问ESB的服务.
public class SendJMSMessage {
public void setupConnection() throws JMSException, NamingException
{
InitialContext iniCtx = new InitialContext();
Object tmp = iniCtx.lookup("ConnectionFactory");
QueueConnectionFactory qcf = (QueueConnectionFactory) tmp;
conn = qcf.createQueueConnection();
que = (Queue) iniCtx.lookup("queue/quickstart_helloworld_action_Request");
session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
conn.start();
System.out.println("Connection Started");
}
public void sendAMessage(String msg) throws JMSException {
QueueSender send = session.createSender(que);
ObjectMessage tm = session.createObjectMessage(msg);
tm.setStringProperty(StoreMessageToFile.PROPERTY_JBESB_FILENAME, "HelloWorldActionTest.log");
send.send(tm);
send.close();
}
public static void main(String args[]) throws Exception
{
SendJMSMessage sm = new SendJMSMessage();
sm.setupConnection();
sm.sendAMessage(args[0]);
sm.stop();
}
}
应该说,这是一个很普通发送JMS消息送到一个指定的Queue. 注意,我这里并无所有拷贝这个SendJMSMessage类. 只是拷贝出重要的部分.(若是想要看完整的,请参考helloworld_action例子下面的代码) ②利用ServiceInvoker直接发送ESB Message 在helloworld_action例子中,没有直接SendESBMessage的客户端来调用,可是咱们能够看下helloworld的sample下面的,由于是同样的.
public class SendEsbMessage
{
public static void main(String args[]) throws Exception
{
// Setting the ConnectionFactory such that it will use scout
System.setProperty("javax.xml.registry.ConnectionFactoryClass","org.apache.ws.scout.registry.ConnectionFactoryImpl");
if (args.length < 3)
{
System.out.println("Usage SendEsbMessage <category> <name> <text to send>");
}
Message esbMessage = MessageFactory.getInstance().getMessage();
esbMessage.getBody().add(args[2]);
new ServiceInvoker(args[0], args[1]).deliverAsync(esbMessage);
}
}
正如咱们以前所说的,客户端用ServiceInvokerAPI大大简化了调用服务的过程. 咱们在jboss-esb.xml中看到每一个service都会有service-category和service-name的属性. 在ServiceInvoker中,用户只须要提供这两个属性,就能调用到ESB的服务,固然了,还须要juddi.properties文件. 这也是为何咱们的 sample下面通常会有这个文件. ServiceInvoker的使用 ServiceInvoker是个至关重要的API,应该说在ESB service之间服务的互相调用,就是用ServiceInvoker来完成的. 由于ServiceInvoker对Courier等进行了一层的抽象封装. 因此用ServiceInvoker来调用服务,是能够支持fail-over等高级特性的. 四、小结 咱们结合以前的概念,来看下这个例子的调用过程. 这里咱们假设是经过JMS Gateway来调用ESB服务的. (1). 从JMS Gateway listener接收到JMS Message.而后把JMS message 转成 ESB Message. (2). 使用ServiceInvoker API发送 ESB Message到指定的service.
(3). ESBAwareListener接收到ESB Mesage后,找到对应的service,把Message提交给ActionProcessingPipeline来处理. 咱们这里讲述了一个简单的调用oneway服务的一个过程. 3、 Jboss ESB的功能点及实例介绍 一、简单的测试经过Jboss ESB服务器进行消息转发的实例 (1)消费者端的代码(即要访问Jboss ESB服务器端的代码,访问者端的代码) 该类的路径在VSS上是: Jboss ESB实例\实例1\book\src\org\jboss\seam\example\booking package org.jboss.seam.example.booking;
import java.util.Hashtable; import javax.jms.JMSException; import javax.jms.ObjectMessage; import javax.jms.Queue; import javax.jms.QueueConnection; import javax.jms.QueueConnectionFactory; import javax.jms.QueueSender; import javax.jms.QueueSession; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException;
import org.jboss.soa.esb.message.format.MessageFactory; import org.jboss.soa.esb.message.format.MessageType; import org.apache.log4j.Logger; import org.jboss.soa.esb.message.Message; import org.jboss.soa.esb.message.format.MessageFactory; import org.jboss.soa.esb.message.format.MessageType;
import org.jboss.soa.esb.client.ServiceInvoker;
public class TestESB { QueueConnection conn; QueueSession session; Queue que; private ServiceInvoker serviceInvoker;
@SuppressWarnings("unchecked") public void setupConnection() throws JMSException, NamingException
{ Hashtable properties1 = new Hashtable(); properties1.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); properties1.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); properties1.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099"); InitialContext iniCtx = new InitialContext(properties1); Object tmp = iniCtx.lookup("ConnectionFactory"); QueueConnectionFactory qcf = (QueueConnectionFactory) tmp;
conn = qcf.createQueueConnection(); que = (Queue) iniCtx.lookup("queue/esb-tb-bankRequestQueue");//("queue/esb-tb-bankRequestQueue");//("queue/quickstart_helloworld_action_Request"); session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE); conn.start(); System.out.println("Connection Started");
}
public void stop() throws JMSException { conn.stop(); session.close(); conn.close(); }
public void sendAMessage(String msg) throws JMSException { QueueSender send = session.createSender(que); ObjectMessage tm = session.createObjectMessage(msg); send.send(tm); send.close(); }
public static void main(String args[]) throws Exception { TestESB sm = new TestESB();
sm.setupConnection(); sm.sendAMessage("yuexiangcheng");
sm.stop(); } 这是一个带有main()函数的主方法,目的就是为了测试。 properties1.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099"); 这句代码中的IP地址,表示Jboss ESB服务器的IP地址。 iniCtx.lookup("queue/esb-tb-bankRequestQueue"); 这句代码中的 queue/esb-tb-bankRequestQueue表示Jboss ESB服务器上暴露的服务接口。
(2)Jboss ESB服务器端的代码。 该实例的代码在VSS的路径是: Jboss ESB实例\实例1\HelloESB Jboss ESB服务器上主要的代码有两部分。 ①jboss-esb.xml 代码以下: <?xml version="1.0"?> <jbossesb xmlns="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd"> <providers> <jms-provider name="JBossMQ" connection-factory="ConnectionFactory"> <jms-bus busid="quickstartGwChannel"> <jms-message-filter dest-type="QUEUE" dest-name="queue/quickstart_helloworld_action_Request" /> </jms-bus> <jms-bus busid="quickstartEsbChannel"> <jms-message-filter dest-type="QUEUE"
dest-name="queue/B" /> </jms-bus>
<!--加被岳乡成 --> <jms-bus busid="creditAgencyRequest"> <jms-message-filter dest-type="QUEUE" dest-name="queue/esb-tb-creditAgencyQueue" /> </jms-bus> <jms-bus busid="bankResponseGateway"> <jms-message-filter dest-type="QUEUE" dest-name="queue/esb-tb-bankGatewayResponseQueue"/> </jms-bus>
<jms-bus busid="bankResponseListener"> <jms-message-filter dest-type="QUEUE" dest-name="queue/esb-tb-bankResponseQueue"/>
</jms-bus>
</jms-provider> </providers> <services> <service category="HelloWorld_ActionESB" name="SimpleListener" description="Hello World" > <listeners> <jms-listener name="JMS-Gateway" busidref="quickstartGwChannel" is-gateway="true" /> <jms-listener name="JMS-ESBListener" busidref="quickstartEsbChannel" /> </listeners> <actions mep="OneWay"> <action name="action2" class="org.jboss.soa.esb.actions.SystemPrintln" /> <action name="displayAction" class="org.jboss.soa.esb.samples.quickstart.helloworldaction.MyJMSListenerAction" process="displayMessage">
<property name="exceptionMethod" value="exceptionHandler"/> </action> <action name="playAction" class="org.jboss.soa.esb.samples.quickstart.helloworldaction.MyJMSListenerAction" process="playWithMessage"> <property name="exceptionMethod" value="exceptionHandler"/> </action> <action name="notificationAction" class="org.jboss.soa.esb.actions.Notifier"> <property name="okMethod" value="notifyOK" />
<property name="notification-details"> <NotificationList type="OK"> <target class="NotifyConsole" /> <target class="NotifyQueues"> <messageProp name="quickstart" value="hello_world_action" /> <queue jndiName="queue/quickstart_helloworld_action_Response"/> </target> </NotificationList>
</property> </action> </actions> </service>
<!--加被岳乡成 --> <service category="tbCreditAGency" name="creditagency" description="Credit Agency Service"> <listeners> <jms-listener name="trailblazer-jmscreditagency" busidref="creditAgencyRequest" maxThreads="1"/> </listeners> <actions>
<action class="org.jboss.soa.esb.samples.quickstart.testbyyuexiangcheng.CreditAgencyActions" process="processCreditRequest" name="fido"> </action> </actions> </service> <service category="tbJmsbank" name="jmsbankreplies" description="Trailblazer Bank Reply Service"> <listeners> <jms-listener name="trailblazer-jmsbank" busidref="bankResponseGateway" maxThreads="1" is-gateway="true"/> <jms-listener name="trailblazer-jmsbankreplies"
busidref="bankResponseListener" maxThreads="1"/> </listeners>
<actions> <action class="org.jboss.soa.esb.samples.quickstart.testbyyuexiangcheng.BankResponseActions" process="processResponseFromJMSBank" name="pepe"/> </actions> </service> </services> </jbossesb> 上面红色部分表示Jboss ESB服务器上暴露的上面要调用的服务的接口的过程。 当通道接收到消息时,就会被拦截,就会转到上面绿色区域定义的类中去处理。 ②Action类
该类的代码在VSS上的路径为: Jboss ESB实例\实例1\HelloESB\src\org\jboss\soa\esb\samples\quickstart\testbyyuexiangcheng
package org.jboss.soa.esb.samples.quickstart.testbyyuexiangcheng;
import java.util.Random;
import org.apache.log4j.Logger; import org.jboss.soa.esb.actions.AbstractActionLifecycle; import org.jboss.soa.esb.helpers.ConfigTree; import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.format.MessageFactory; import org.jboss.soa.esb.message.format.MessageType; import org.jboss.soa.esb.util.Util;
public class CreditAgencyActions extends AbstractActionLifecycle { protected ConfigTree _config;
private static Logger _logger = Logger.getLogger(CreditAgencyActions.class);
public CreditAgencyActions(ConfigTree config) { _config = config; }
public Message noOperation(Message message) { return message; }
public Message processCreditRequest(Message message) throws Exception{
_logger.debug("message received: " + Util.serialize(message) );
String csvData = (String) message.getBody().get(); _logger.debug("csv data received: " + csvData);
//generate a random score between 1 and 10 Random rand = new Random(); int n = 10; int score = rand.nextInt(n+1);
//send back the reply Message replyMessage = MessageFactory.getInstance().getMessage(MessageType.JBOSS_XML); _logger.info("CreditAgency sending back a credit score of " + score); replyMessage.getBody().add(Integer.toString(score));
return replyMessage; }
public Message debugMessage(Message message) throws Exception{
_logger.debug("message received in processCreditRequest with message: " + Util.serialize(message));
return message; } } 二、 读取外部文档的数据,发送到Jboss ESB服务器上而且进行数据转换。 该实例的工程在VSS上的路径是: Jboss ESB实例\实例2\James 该实例主要要注意三点: ①在工程中要提供一个要读取的文件,好比该实例中的SampleOrder.csv文件。 该文件在VSS上的路径为: Jboss ESB实例\实例2\James\src\test
固然Jboss ESB还能够读取多种类型的文件,好比.xml文档等。
②调用者端的代码 该类在VSS的路径以下: Jboss ESB实例\实例2\James\src\test
package test;
import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Hashtable;
import javax.jms.JMSException; import javax.jms.ObjectMessage;
import javax.jms.Queue; import javax.jms.QueueConnection; import javax.jms.QueueConnectionFactory; import javax.jms.QueueSender; import javax.jms.QueueSession;
import javax.naming.Context;
import javax.naming.InitialContext; import javax.naming.NamingException;
import org.jboss.soa.esb.util.FileUtil;
public class testCvsMassage { QueueConnection conn; QueueSession session; Queue que; public void setupConnection() throws JMSException, NamingException {
Hashtable properties1 = new Hashtable(); properties1.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); properties1.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); properties1.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099"); // InitialContext iniCtx = new InitialContext(properties1);
// Object tmp = iniCtx.lookup("ConnectionFactory"); // QueueConnectionFactory qcf = (QueueConnectionFactory) tmp;
// conn = qcf.createQueueConnection(); // que = (Queue) iniCtx.lookup("queue/esb-tb-bankRequestQueue");//("queue/esb-tb-bankRequestQueue");//("queue/quickstart_helloworld_action_Request"); // session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE); // conn.start(); // System.out.println("Connection Started"); InitialContext iniCtx = new InitialContext(properties1); Object tmp = iniCtx.lookup("ConnectionFactory"); QueueConnectionFactory qcf = (QueueConnectionFactory) tmp; conn = qcf.createQueueConnection(); que = (Queue) iniCtx.lookup("queue/quickstart_transform_CSV2XML_gw"); session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE); conn.start(); System.out.println("Connection Started"); } public void stop() throws JMSException { conn.stop(); session.close(); conn.close(); } public void sendAMessage(String fileName) throws JMSException, FileNotFoundException, IOException {
QueueSender send = session.createSender(que); ObjectMessage tm; File file = new File(fileName); if(!file.exists()) { throw new IllegalArgumentException("Input message file [" + file.getAbsolutePath() + "] not found."); }
String message = FileUtil.readTextFile(file);
tm = session.createObjectMessage(message); tm.setStringProperty("jbesbfilename", "transformedmessageCSV2XML.log"); send.send(tm); send.close(); System.out.println("*** Switch back to the ESB Java console now to see '" + fileName + "' before and after the transformation...");
} public static void main(String args[]) throws Exception { testCvsMassage sm = new testCvsMassage(); sm.setupConnection(); sm.sendAMessage("SampleOrder.csv"); sm.stop(); } } 上面的这句代码sm.sendAMessage("SampleOrder.csv");表示读取SampleOrder.csv文件中的内容。 ③Jboss ESB端的代码 该代码在VSS上的路径为: Jboss ESB实例\实例2\HelloESB\src\META-INF Ⅰ、jboss-esb.xml <?xml version="1.0"?> <jbossesb xmlns="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd"> <providers>
<jms-provider name="JBossMQ" connection-factory="ConnectionFactory">
<jms-bus busid="quickstartGwChannel"> <jms-message-filter dest-type="QUEUE" dest-name="queue/quickstart_helloworld_action_Request"
/> </jms-bus> <jms-bus busid="quickstartEsbChannel">
<jms-message-filter dest-type="QUEUE" dest-name="queue/B"
/> </jms-bus> <!--加被岳乡成 --> <jms-bus busid="creditAgencyRequest"> <jms-message-filter dest-type="QUEUE" dest-name="queue/esb-tb-creditAgencyQueue" /> </jms-bus> <jms-bus busid="bankResponseGateway"> <jms-message-filter dest-type="QUEUE" dest-name="queue/esb-tb-bankGatewayResponseQueue"/> </jms-bus> <jms-bus busid="bankResponseListener"> <jms-message-filter dest-type="QUEUE" dest-name="queue/esb-tb-bankResponseQueue"/> </jms-bus> <!--加被岳乡成 --> <jms-bus busid="quickstartCSVGwChannel">
<jms-message-filter dest-type="QUEUE" dest-name="queue/quickstart_transform_CSV2XML_gw" /> </jms-bus>
<jms-bus busid="quickstartCSVEsbChannel"> <jms-message-filter dest-type="QUEUE" dest-name="queue/quickstart_transform_CSV2XML_esb" />
</jms-bus>
</jms-provider> </providers> <services> <service category="HelloWorld_ActionESB" name="SimpleListener"
description="Hello World" > <listeners> <jms-listener name="JMS-Gateway" busidref="quickstartGwChannel" is-gateway="true" /> <jms-listener name="JMS-ESBListener" busidref="quickstartEsbChannel"
/> </listeners>
<actions mep="OneWay"> <action name="action2" class="org.jboss.soa.esb.actions.SystemPrintln" /> <action name="displayAction" class="org.jboss.soa.esb.samples.quickstart.helloworldaction.MyJMSListenerAction" process="displayMessage"> <property name="exceptionMethod" value="exceptionHandler"/>
</action> <action name="playAction" class="org.jboss.soa.esb.samples.quickstart.helloworldaction.MyJMSListenerAction" process="playWithMessage"> <property name="exceptionMethod" value="exceptionHandler"/> </action> <action name="notificationAction" class="org.jboss.soa.esb.actions.Notifier"> <property name="okMethod" value="notifyOK" /> <property name="notification-details"> <NotificationList type="OK"> <target class="NotifyConsole" /> <target class="NotifyQueues"> <messageProp name="quickstart" value="hello_world_action" /> <queue jndiName="queue/quickstart_helloworld_action_Response"/> </target> </NotificationList> </property> </action>
</actions> </service>
<!--加被岳乡成 --> <service category="tbCreditAGency" name="creditagency" description="Credit Agency Service"> <listeners> <jms-listener name="trailblazer-jmscreditagency" busidref="creditAgencyRequest" maxThreads="1"/> </listeners> <actions> <action class="org.jboss.soa.esb.samples.quickstart.testbyyuexiangcheng.CreditAgencyActions" process="processCreditRequest" name="fido"> </action> </actions> </service> <service category="tbJmsbank" name="jmsbankreplies" description="Trailblazer Bank Reply Service"> <listeners> <jms-listener name="trailblazer-jmsbank" busidref="bankResponseGateway" maxThreads="1" is-gateway="true"/> <jms-listener name="trailblazer-jmsbankreplies" busidref="bankResponseListener"
maxThreads="1"/> </listeners> <actions> <action class="org.jboss.soa.esb.samples.quickstart.testbyyuexiangcheng.BankResponseActions" process="processResponseFromJMSBank" name="pepe"/> </actions> </service> <!--加被岳乡成 --> <service category="QuickstartTransformCSV" name="SimpleListener" description="Hello World"> <listeners>
<jms-listener name="CSVJMS-Gateway" busidref="quickstartCSVGwChannel" is-gateway="true"/> <jms-listener name="CSVquickstart" busidref="quickstartCSVEsbChannel"/> </listeners>
<actions mep="OneWay"> <!--
Note that with this quickstart, the transformation is broken into 2 transforms; CSV to XML and XML to XML. These 2 transformations could easly be merged into a single transform, saving on XML processing. -->
<action name="print-before" class="org.jboss.soa.esb.actions.SystemPrintln"> <property name="message" value="[transform_CSV2Smooks_Intermediate_format] Message before CVS to XML transformation" /> </action>
<!-- Transform. 1: Source CSV to Canonical XML... --> <action name="transform-from-csv" class="org.jboss.soa.esb.smooks.SmooksAction"> <property name="smooksConfig" value="/smooks-res.xml" /> <property name="messageProfile" value="source-csv" /> </action>
<action name="print-after-csv-tranform" class="org.jboss.soa.esb.actions.SystemPrintln"> <property name="message" value="[transform_CSV2Smooks_Intermediate_format] Message after CVS to XML transformation" /> </action>
<!-- Transform. 2: Canonical XML to target XML... -->
<action name="transform-to-xml" class="org.jboss.soa.esb.smooks.SmooksAction"> <property name="smooksConfig" value="/smooks-res.xml" /> <property name="messageProfile" value="canonical-xml" /> </action>
<action name="print-after-xml-transform" class="org.jboss.soa.esb.actions.SystemPrintln"> <property name="message" value=">>>> Message after Smooks intermediate xml -> target xml : " /> </action>
</actions>
</service> </services> </jbossesb> 上面绿色区域的代码表示Jboss ESB服务器把.cvs文件转换为.xml文件的过程。 <action name="transform-from-csv" class="org.jboss.soa.esb.smooks.SmooksAction">这句代码中的class="org.jboss.soa.esb.smooks.SmooksAction"是Jboss ESB提供的。 Jboss ESB提供了好多关于数据转换的例子,请详细参考。
三、 基于内容的路由 关于内容的路由,我在这里就不详细说了,请详细参考: jbossesb-4.4.GA\samples\quickstarts下的
四、 Jboss ESB的业务流 关于Jboss ESB的业务流,我在这里也不详细说了,请详细参考: jbossesb-4.4.GA\samples\quickstarts下的
五、 以JMS为消息在Jboss ESB上的一个应用。
该实例的源码在VSS上的路径是: SOA\ JMS在Jboss ESB中的应用 这个实例包括三个部分<1>Jboss ESB服务器端(192.168.1.101 esb文件夹下的工程)。<2>服务消费者端(192.168.1.111文件夹下的工程)。<3>服务提供者端(192.168.1.121文件夹下的工程)。
①Jboss ESB服务器端 Ⅰ、Jboss-esb.xml文件 该文件在VSS上的路径为:
JMS在Jboss ESB中的应用\192.168.1.101 esb\Medicare_esb\src\META-INF <?xml version = "1.0" encoding = "UTF-8"?> <jbossesb xmlns="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd" parameterReloadSecs="5">
<providers> <jms-provider name="JBossMQ" connection-factory="ConnectionFactory"> <jms-bus busid="quickstartGwChannel"> <jms-message-filter dest-type="QUEUE" dest-name="queue/quickstart_transform_pojo_gw" /> </jms-bus> <jms-bus busid="quickstartEsbChannel"> <jms-message-filter dest-type="QUEUE" dest-name="queue/quickstart_transform_pojo_esb"
/> </jms-bus>
</jms-provider> </providers> <services> <service category="MyTransformationServicesESB" name="MyFirstTransformationServiceESB" description="ESB: Takes XML in and produces a POJO"> <listeners> <jms-listener name="JMS-Gateway" busidref="quickstartGwChannel" is-gateway="true" /> <jms-listener name="jmsTransformer" busidref="quickstartEsbChannel" /> </listeners> <actions mep="OneWay">
<action name="displayBeforeTransformer" class="org.jboss.soa.esb.samples.medicare.MyJMSListenerAction"
process="displayMessage" />
<action name="returnToSender" class="org.jboss.soa.esb.samples.medicare.MyJMSListenerAction" process="sendResponse" /> <!-- <action name="receiveMsg" class="org.jboss.soa.esb.samples.medicare.ReceiveMessage" process="displayMessage" />
<action name="receiveMsg"
class="org.jboss.soa.esb.samples.medicare.ReceiveMessage" process="sendResponse" /> --> </actions> </service> </services>
</jbossesb> Ⅱ、 在Jboss ESB服务器上的Action 在VSS上的路径为: JMS在Jboss ESB中的应用\192.168.1.101 esb\Medicare_esb\src\org\jboss\soa\esb\samples\medicare 这个文件夹下的内容就是消息的拦截器,负责对消息的拦截。详细内容请查看相关的代码。
②消费者端的代码。
该工程在VSS上的路径为: JMS在Jboss ESB中的应用\192.168.1.121 相关的代码请详细参考该工程。 ③提供者端的代码。
该工程在VSS上的路径为: JMS在Jboss ESB中的应用\192.168.1.111 相关的代码请详细参考该工程。 六、 以Web Service为基础在Jboss ESB上的一个应用。 该工程在VSS上的路径为: SOA\SOA(V1.2) 这个实例也包括三个部分<1>Jboss ESB服务器端(Esb Service(192.168.1.101)文件夹下的工程)。<2>服务消费者端(Request endpoint(192.168.1.112)文件夹下的工程)。<3>服务提供者端(Respose endpoint(192.168.1.111)文件夹下的工程)。 服务消费者端和服务提供者端我已经在另外一个文档中《Web Service简介及开发实例》中作了详细的介绍。 如今我只简单的讨论一下再Jboss ESB服务器端的代码。 ①先看Jboss-esb.xml文件 该文件在VSS上的路径为: SOA(V1.2)\Esb Service(192.168.1.101)\WebService\src\META-INF <?xml version = "1.0" encoding = "UTF-8"?>
<jbossesb xmlns="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd" parameterReloadSecs="5">
<providers> <jms-provider name="JBossMQ" connection-factory="ConnectionFactory">
<jms-bus busid="quickstartGwChannel"> <jms-message-filter dest-type="QUEUE" dest-name="queue/quickstart_webservice_producer_gw"/>
</jms-bus> <jms-bus busid="quickstartEsbChannel"> <jms-message-filter dest-type="QUEUE" dest-name="queue/quickstart_webservice_producer_esb"/>
</jms-bus> </jms-provider>
<jbr-provider name="JBR-Http" protocol="http" > <jbr-bus busid="Http-1" port="8765" /> </jbr-provider>
<jbr-provider name="JBR-Socket" protocol="socket" host="localhost"> <jbr-bus busid="Socket-1" port="8888" />
</jbr-provider>
</providers>
<services>
<service category="MyServiceCategory" name="MyWSProducerService" description="WS Frontend speaks natively to the ESB">
<listeners>
<jms-listener name="JMS-Gateway" busidref="quickstartGwChannel" is-gateway="true"/> <jbr-listener name="Http-Gateway" busidref="Http-1" is-gateway="true"/> <jbr-listener name="Socket-Gateway" busidref="Socket-1" is-gateway="true"/>
<jms-listener name="JMS-ESBListener" busidref="quickstartEsbChannel"/> </listeners> <actions> <action name="print-before" class="org.jboss.soa.esb.actions.SystemPrintln"> <property name="message" value="[Quickstart_webservice_producer] BEFORE invoking jbossws endpoint"/> </action> <action name="JBossWSAdapter" class="org.jboss.soa.esb.actions.soap.SOAPProcessor"> <property name="jbossws-endpoint" value="GoodbyeWorldWS"/> </action> <action name="print-after" class="org.jboss.soa.esb.actions.SystemPrintln">
<property name="message"
value="[Quickstart_webservice_producer] AFTER invoking jbossws endpoint"/> </action> <action name="testStore" class="org.jboss.soa.esb.actions.TestMessageStore"/> </actions> </service>
</services>
</jbossesb> ②Jboss ESB服务器上的Action类,代码以下: 该类在VSS上的路径为: SOA(V1.2)\EsbService(192.168.1.101)\WebService\src\org\jboss\soa\esb\samples\quickstart\webserviceproducer\webservice 代码以下: package org.jboss.soa.esb.samples.quickstart.webserviceproducer.webservice;
import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List;
import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; import javax.xml.soap.MessageFactory; import javax.xml.soap.Name; import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPConnection; import javax.xml.soap.SOAPConnectionFactory; import javax.xml.soap.SOAPConstants; import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPFactory; import javax.xml.soap.SOAPMessage; import javax.xml.soap.SOAPPart; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.stream.StreamResult;
/** * @author
*/ @WebService(name = "GoodbyeWorldWS", targetNamespace="http://webservice_producer/goodbyeworld") public class GoodbyeWorldWS {
public static final String INDEXOFOBJECTSTART = "<Hotel>"; public static final String INDEXOFOBJECTEND = "</Hotel>"; public static final int BJECTSTARTFLAGLENGTH = INDEXOFOBJECTSTART.length(); public static final int BJECTENDFLAGLENGTH = INDEXOFOBJECTEND.length();
@WebMethod @WebResult(name="ListHotel") public String sayGoodbye(@WebParam(name="message") String message){ try {
//传送参数须要建立Name
SOAPFactory soapFactory = SOAPFactory.newInstance(); //Next, create the actual message MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage message1 = messageFactory.createMessage(); //Create objects for the message parts SOAPPart soapPart = message1.getSOAPPart(); SOAPEnvelope envelope = soapPart.getEnvelope(); SOAPBody body = envelope.getBody(); //Populate the body //Create the main element and namespace
SOAPElement bodyElement = body.addChildElement(envelope.createName("getHotelObject" , "serch", "http://tower/ehr_DEV")); bodyElement.setEncodingStyle(SOAPConstants.URI_NS_SOAP_ENCODING); //传送参数新建一个Name对象 Name name = soapFactory.createName("arg0");
SOAPElement symbol = bodyElement.addChildElement(name); symbol.addTextNode(message); //Add content //Save the message message1.saveChanges(); //Send the message and get a reply //Set the destination //Send the message
List<String> destinationList = readTxtFile("D:/webServiceConfig.txt"); String resultString = getResultString(destinationList,message1); if("".equals(resultString)){ return ""; }else{
return resultString; } } catch(Exception e) {
System.out.println(e.getMessage()); } return "";
}
public static List<String> readTxtFile(String fileName){ String read;
FileReader fileread; List<String> l = new ArrayList<String>(); try { fileread = new FileReader(fileName); BufferedReader bufread = new BufferedReader(fileread);
try { while ((read = bufread.readLine()) != null) {
l.add(read); } } catch (IOException e) { } } catch (FileNotFoundException e) {
e.printStackTrace(); } return l; } public static String getResultString(List<String> destinationList,SOAPMessage message){ try { String resultString = ""; for(int i = 0;i<destinationList.size();i++){
String destination = destinationList.get(i); SOAPConnectionFactory soapConnFactory = SOAPConnectionFactory.newInstance(); SOAPConnection connection = soapConnFactory.createConnection();
SOAPMessage reply = connection.call(message, destination); String stringBady = getSOAPMessageStringBady(reply); resultString = resultString + stringBady; connection.close(); } return resultString; } catch (UnsupportedOperationException e) { e.printStackTrace(); } catch (SOAPException e) { e.printStackTrace(); } return ""; }
public static String getSOAPMessageStringBady(SOAPMessage reply) { try { String sb = ""; Source source = reply.getSOAPPart().getContent(); Transformer transformer = TransformerFactory.newInstance().newTransformer(); ByteArrayOutputStream myOutStr = new ByteArrayOutputStream(); StreamResult res = new StreamResult(); res.setOutputStream(myOutStr); transformer.transform(source,res); String temp = myOutStr.toString().trim(); int indexOfObjectStart = temp.indexOf(INDEXOFOBJECTSTART); if(indexOfObjectStart==-1){ return sb; }else{ int indexOfObjectEnd = temp.lastIndexOf(INDEXOFOBJECTEND); sb = temp.substring(indexOfObjectStart,indexOfObjectEnd+OBJECTENDFLAGLENGTH); return sb; } } catch (TransformerConfigurationException e) { e.printStackTrace(); } catch (TransformerFactoryConfigurationError e) { e.printStackTrace(); } catch (SOAPException e) { e.printStackTrace(); } catch (TransformerException e) { e.printStackTrace(); }
return ""; }
}