JBoss ESB 4.x 介绍

来源:百度文库 编辑:神马文学网 时间:2024/06/05 05:48:03
JBoss ESB 4.x 介绍

JBoss ESB 4.x 介绍

1. 总述
2. JBossESB的概念
2.1. Message (消息)
2.2. Service (服务)
2.3. Listeners, Gateway
2.4. Couriers
2.5. Actions
2.6. Meta-data and Filters
2.7. ServiceInvoker

3. JBoss ESB 例子
3.1. 安装和运行JBossESB sample
3.2. 分析helloworld_action例子
3.3. 客户端调用服务
3.4. 小结
4. JBoss ESB 部署和集成模块
4.1. JBoss ESB Deployer
4.2. JBoss ESB Service 集成

5. 总结Bibliography[b]

Abstract[/b]
        这篇文章主要是介绍了JBoss ESB的基础架构,以及通过一个简单的例子来认识JBoss ESB.  

[size=5][b]1. 总述[/b][/size]
        JBossESB是JBoss推出的ESB的实现,也是JBoss的SOA产品的基础.首先大家对于ESB的定义有很多的不同,我个人更喜欢把ESB看作是系统集成的一个平台.         JBossESB是一个基于消息的中间件(Message Oriented). 在这篇文章中,我们只是看待ESB中的一个很基础部份,也就是怎么从Endpoint A发送信息给ESB的服务S1,然后再有S1发送信息到Endpoint B去调用服务.        至于其他的Router(路由)或者Data Transformation(数据转换),这里赞不介绍.    
我们就假设一个简单的系统集成场景来开始阐述JBossESB的设计和概念.
A系统(Endpoint A) –  Message ->  ESB -> –  Message --> B系统 (Endpoint B)[/pre] 所以,如果简单的对于JBossESB定义的话,我们可以定义以下三个概念:
[list][li]Message Listener (接收“inbound” message)[/li][li]            Message Filter (发送 \"outbound” message)        [/li][li]            Message (消息对象)        [/li][/list]        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[/pre]        那么在ESB内部是怎么去表达一个服务呢?这里引入了EndpointReference的概念,简称EPR.         有了服务之后,服务之间是通过什么样的传输层(比如JMS, FTP, HTTP)来通信呢?         所以ESB的内部也引入了Courier的API, 来统一抽象传输层. 刚我们也看到了,ESB的内部无非就是一系列的服务,        但是我们怎么来保存/注册这些服务的呢? JBossESB是使用jUDDI来注册和保存这些服务元数据的.    
[size=5][b]2. JBossESB的概念[/b][/size]
在要了解和运行JBossESB之前,我们最好了解下JBossESB中比较重要的几个概念
[size=4][b]2.1. Message (消息)[/b][/size]
ESB内部所交流/传递的都是消息,所以可见这个消息格式的重要性. 在JBossESB中, 定义了一个Message的对象,它是有以下几个部分构成的.
[list=1][li]Header (用来存放From, To, Reply-to等Addressing的信息).[/li][li]Body (存放信息主体)[/li][li]Attachment (用来存放附件等)[/li][li]Properties[/li][li]Context (主要是存放一些类似事务的信息等)[/li][/list]
           目前在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.       

[size=4][b]2.2. Service (服务)[/b][/size]
            ESB的内部服务是用EPR来映射的. ESB的内部服务可以是任何的一个服务,比如说一个FTP的服务,一个基于文件系统的服务等等,            那么这个时候我们就需要用EPR来对这个服务进行描述.在EPR这个类里,主要是描述了这个服务的URI,以及所必须的一些元数据.             目前在JBossESB中提供的EPR有: FileEPR,EmailEPR,FTPEPR, HibernateEPR等等. 我们在注册服务的时候,是将EPR的信息注册到UDDI的容器里,            但不仅仅是EPR, 还有一些辅助信息,比如定义服务的category-name, service-name. 这些将在后面继续介绍.       

[size=4][b]2.3. Listeners, Gateway[/b][/size]

            Listener的作用是负责监听端口,一般来说,客户端是发送消息到Listener,然后有Listener把消息传递给ESB,            我们可以把Listener看做是inbound router. 在JBossESB中,我们是叫GatewayListener, 它一般来说做两件事情.        
[list][li] 监听Message.            [/li][li]ESB-unaware message和 ESB-aware message的互转.[/li][/list]            目前ESB支持的Gateway有: JMSGatewayListener, JBossRemotingGatewayListener, FileGatewayListener等等.             在[b]MessageComposer[/b]这个类里的compose/decompose方法来负责ESB-unaware信息和ESB-aware信息的转化.        

public interface MessageComposer {

/**

     * 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;

}

[size=4][b]2.4. Couriers[/b][/size]
            Courier的作用就是负责传输,正如以下接口所显示:        
public interface Courier extends DeliverOnlyCourier
{
    public boolean deliver(Message message)     throwsCourierException,MalformedEPRException;
}
        目前实现的Transport有:JmsCourier, InVMCourier, HibernateCourier, FileCourier等传输层,在ESB内部是通过EPR来跟Courier进行关联的.       

[size=4][b]2.5. Actions[/b][/size]

            在JBossESB中,我们可以把ActionProcessingPipeline类看作是Message Filter, 每个Message都会经过    ActionProcessingPipeline的处理. 里面有这么个方法:        
public boolean process(final Message message)
                而actionProcessingPipeline又是由Action (ActionPipelineProcessor)来组成的. 我们可以把Action看成是Interceptor, 由它来实现具体的业务逻辑,可以是路由,又或者数据转化功能等等.            如果你用JBossESB的话,那么Action是一个非常重要的部分,我们来看下它所定义的接口.        
public interface ActionPipelineProcessor extends ActionLifecycle
{  
     public Message process(final Message message) throws ActionProcessingException ;
     public void processException(final Message message, final Throwable th) ;
     public void processSuccess(final Message message) ;
}
        [/pre]一般来说自定义的Action把具体的业务逻辑放在Process的方法里,当然了,你也可以定义相对应的Exception处理方法,通过实现processException.在ESB代码中,自定义的Action可以用继承AbstractActionPipelineProcessor或者 AbstractActionLifecycle.
[size=4][b]
2.6. Meta-data and Filters[/b][/size]
            在有些情况下,你需要一些全局的Interceptor,我们之前说的Action,可以理解成是每个service的interceptor,但是如果我需要使用log来记录一个消息在各个service之间传输的日志,            又或者想记录消息进入某个service的时间和退出的时间. 那么在JBoss ESB中就有[b]Filter[/b]的概念.            如果你要实现自己的Filter,需要继承[b]InputOputFilter[/b]类.        

public class InputOutputFilter

{

/**

     * Called as the message flows towards the transport.

     */



public Message onOutput (Message msg, Map params) throws CourierException

{

return msg;

}



/**

     * Called immediately after the message is received from the transport.

     */



public Message onInput (Message msg, Map params) throws CourierException

{

return msg;

}

}


[size=5][b]Tip[/b][/size]
            写完自己的Filter后,你需要在$JBossESB/server/config (e.g. default)/deploy/jbossesb.sar/jbossesb-properties.xml里面增加filter.            需要注意的是,在这里配置的filter是对所有的esb包都起作用,是个全局的变量.        
        [b]onInput[/b]方法总是在从传输层获取到Message后,第一步所做的工作;类似的,   
    [b]onOutput[/b]是给传输层传递前所做的最后一步工作. 你可以在[b]TwoWayCourierImpl[/b]中看到这段代码的调用.    
[size=4][b]
2.7. ServiceInvoker[/b][/size]
            对于客户端调用来说,EPR, Courier等都太底层了.所以如果对此进行了封装. 我们对每个service加以service-category和service-name的属性.            所以如果你想发送一个ESB的内部Message,你只需要知道目标service的service-category和service-name,然后就可以调用[b]ServiceInvoker[/b]来调用服务.            不需要去使用Courier等底层的API, 另外用[b]ServiceInvoker[/b]还可以支持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

}


[size=5][b]3. JBoss ESB 例子[/b][/size]
为了更好的来解释JBossESB, 最好的一个方法就是试下JBossESB自带的例子,这里我们先以helloworld_action的例子来讲解.
[size=4][b]3.1. 安装和运行JBossESB sample[/b][/size]

到这里,你已经成功的运行了helloworld_action的例子.
[list=1][li]从[url=http://www.jboss.org/jbossesb/downloads]JBossESB[/url]网站下载 jbossesb-server-4.4.GA.zip[/li][li]解压jbossesb-server-4.4.GA.zip, 假设到/var/local/jbossesb-sever4.4. 下面以$jbossesb来替代.[/li][li]在$jbossesb中,运行 bin/run.sh 来启动ESB server[/li][li]另外打开一个窗口,到$jbossesb/samples/quickstarts/helloworld_actions, 运行: ant deploy[/li][li]再运行: ant runtest[/li][li]                  回到JBoss ESB server的控制台上,应该可以看到以下的输出:                  INFO  [STDOUT] [Hello World Action].
INFO  [STDOUT]
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
INFO  [STDOUT] Body: Hello World Action
INFO  [STDOUT] &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
INFO  [STDOUT] ConsoleNotifier 2008/09/26 06:35:39.643<
BEFORE**
Hello World Action
AFTER**
>
[/pre][/li][/list]
[size=4][b]3.2. 分析helloworld_action例子[/b][/size]
下面我们来具体看下helloworld_action这个例子. 在JBoss ESB 4.4的例子中,我们默认以JBoss Messaging来作为JMS的实现.
[size=3][b]3.2.1. jboss-esb.xml[/b][/size]
在看jboss-esb.xml的配置时候,我们应该分成两个部份. providers和services.
[size=2][b]3.2.1.1. providers[/b][/size]
                      首先是,它是有一系列的组成, 目前有jms-provider, fs-provider, ftp-provider等等.然后我们在provider里面定义这个.esb文件里面service所定义的listener所需要的bus,Bus可以简单理解成消息传送所需要的传输层.正如以下所显示的,我们定义了两个Bus,一个是给Gateway的Listener用,另外一个是给ESB-awareMessage传输所需要的传输层.












dest-type=\"QUEUE\"

dest-name=\"queue/quickstart_helloworld_action_Request\"

/>






dest-type=\"QUEUE\"

dest-name=\"queue/B\"

/>











[size=5][b]Tip[/b][/size]
                  虽然在这边写的是[b]JBossMQ[/b], 但是对于JBoss ESB server来说,是默认使用JBoss Messaging的; 如果是把JBoss ESB安装在JBoss AS 4.x的服务器,                  那么就是用JBoss MQ, 因为JBoss AS 4.x默认是使用JBoss MQ.              
[size=2][b]3.2.1.2. services[/b][/size]
              第二部份就是定义services的部份, 在这里定义了当前这个esb包所提供的services. 每个service又是由 组成的.          








name=\"SimpleListener\"

description=\"Hello World\" >




busidref=\"quickstartGwChannel\"

is-gateway=\"true\"

/>


busidref=\"quickstartEsbChannel\"

/>






class=\"org.jboss.soa.esb.actions.SystemPrintln\"

/>


class=\"org.jboss.soa.esb.samples.quickstart.helloworldaction.MyJMSListenerAction\"

process=\"displayMessage\">






class=\"org.jboss.soa.esb.samples.quickstart.helloworldaction.MyJMSListenerAction\"

process=\"playWithMessage\">













[b]
[/b][size=5][b]Warning[/b][/size]
                      在listener里,我们通过[b] busidref[/b]来关联到我们定义在provider里面的bus.                      在这里,我们定义了两个listener. 其中一个是做为Gateway,只负责从外界获取到JMS的消息,然后转成ESB内部所需要的Message.                       而另外一个listener是用来这个Message在services内部之间通讯的通道. 所以对于每个service来说,一定要至少定义一个listener来作为内部Message传输用.                  
这里的[b]action[/b]是对消息(Message)处理的地方.
[size=3][b]3.2.2. MyJMSListenerAction[/b][/size]
              正如我们在上面看到的,我们在[b]jboss-esb.xml[/b]中定义了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;

   }

}



[b]
[/b][size=5][b]Tip[/b][/size]
              我们只是截取其中的一部分来说明,一般来说每个Action都要继承[b]AbstractActionLifecycle[/b]类,然后输入/输出参数都必须是[b]ESB的Message[/b]. 方法名可以随便定义.               你只需要在[b]jboss-esb.xml[/b]的[b]action[/b]的process属性中写相对应的方法名就可以.              如果不写,默认是[b]process[/b]方法.          
                这里的[b]ConfigTree[/b]是个很重要的属性,我们很经常的会在[b]Action[/b]配置其他的信息,那么                所有的信息都可以通过ConfigTree来获取到.比如说在某个Action中配置静态路由信息等等.也正是由于Action中你可以随意的配置你自己的信息,增加了很多的灵活性和扩展性.            
[size=3][b]3.2.3. esb文件目录结构[/b][/size]
              我们先看下部署在server下的.esb包的文件目录,一般是包括以下些东西.          
[list][li]/META-INF/jboss-esb.xml[/li][li] /META-INF/deployment.xml 在这里定义对其他包或者服务的依赖,或者配置classloader.[/li][li]jbm-queue-service.xml (optional) 这里是定义启动所需要的Queue[/li][li]**.jar (optional) 放些所需要的第三方包[/li][li]所需要的些classes文件[/li][/list]
[b]
[/b][size=4][b]3.3. 客户端调用服务[/b][/size]
目前在JBossESB中,一般有两种方式来调用service. 一种是通过Gateway listener, 另外一种是直接通过[b]ServiceInvoker[/b]的API来调用.
[size=3][b]3.3.1. 通过Gateway来调用服务[/b][/size]
回到我们的例子,我们通过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. [b]注意,我这里并没有全部拷贝这个SendJMSMessage类.[/b]             只是拷贝出重要的部分.(如果想要看完整的,请参考helloworld_action例子下面的代码)        
[size=3][b]3.3.2. 利用ServiceInvoker直接发送ESB Message[/b][/size]
                在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   \");

}



Message esbMessage = MessageFactory.getInstance().getMessage();

        esbMessage.getBody().add(args[2]);

new ServiceInvoker(args[0], args[1]).deliverAsync(esbMessage);



}

}

     正如我们之前所说的,客户端用[b]ServiceInvoker[/b]API大大简化了调用服务的过程.                  我们在[b]jboss-esb.xml[/b]中看到每个[b]service[/b]都会有service-category和service-name的属性.                  在ServiceInvoker中,用户只需要提供这两个属性,就能调用到ESB的服务,当然了,还需要[b]juddi.properties[/b]文件. 这也是为什么我们的                  sample下面一般会有这个文件.              
[size=5][b]
ServiceInvoker的使用[/b][/size]
                  ServiceInvoker是个相当重要的API,应该说在ESB service之间服务的互相调用,就是用ServiceInvoker来完成的. 因为ServiceInvoker对Courier等进行了一层的抽象封装.                  所以用ServiceInvoker来调用服务,是可以支持fail-over等高级特性的.                            
[size=4][b]3.4. 小结[/b][/size]
            我们结合之前的概念,来看下这个例子的调用过程. 这里我们假设是通过JMS Gateway来调用ESB服务的.            
[list=1][li]从[b]JMS Gateway listener[/b]接收到JMS Message.然后把JMS message 转成 ESB Message.[/li][li]使用[b]ServiceInvoker[/b] API发送 ESB Message到指定的service.[/li][li][b]ESBAwareListener[/b]接收到ESB Mesage后,找到对应的service,把Message提交给ActionProcessingPipeline来处理.[/li][/list]
                我们这里讲述了一个简单的调用oneway服务的一个过程.            

[size=5][b]4. JBoss ESB 部署和集成模块[/b][/size]
       通过前两个部分的介绍,应该说JBoss ESB简单的内部框架应该比较清楚了. 但是我们还没有涉及到其他部署和集成的一些模块.       正因为通过比如对Smooks, JBoss Rules, jBPM等的集成,使得JBoss ESB的功能更加强大,好用.  
[size=4][b]4.1. JBoss ESB Deployer[/b][/size]
            因为JBoss ESB 4.系列是基于JBoss AS的,所以有个扩展类[b]JBoss4ESBDeployer[/b]类是来负责对JBoss ESB包的监听和解析.            我们可以看到在$jbossesb.sar/META-INF/jboss-service.xml里面定义了JBoss4ESBDeployer的服务.      




name=\"jboss.esb:service=ESBDeployer\">

jboss.esb:service=ESBRegistry

jboss.esb:service=JuddiRMI





[/pre]           所以,通过部署了JBoss4ESBDeployer,凡是以.esb结尾的包,都是由JBoss4ESBDeployer来解析, 如果你对这块比较感兴趣,还可以看下以下的几个类.        
           org.jboss.soa.esb.listeners.config.ConfigurationController
           org.jboss.soa.esb.listeners.config.JBoss4ESBDeployment
           org.jboss.soa.esb.listeners.config.Generator
    
[size=4][b]4.2. JBoss ESB Service 集成[/b][/size]
            正如我们之前所看到的,因为JBossESB内部本身的架构比较灵活,所以说你只要写个自己的[b]Action[/b],可以很方面的做和其他library的集成.            直到JBoss ESB 4.4.GA版本,有以下一系列的集成.        
[list][li]Smooks的集成. (主要是负责数据转化等的服务).[/li][li]JBoss Rules的集成. (可以使用Rules来定义你的路由,这里默认提供了Content-based Router)的功能.[/li][li]jBPM的集成. (可以提供访问jBPM提供的工作流服务)[/li][li]Soap-UI的集成. (负责跟webservice打交道)[/li][li]Spring的集成. (访问Spring提供的服务)[/li][li]slsb (访问无状态SessionBean提供的服务)[/li][li]wise的集成. (另外一种方式通过跟web service打交道)[/li][/list][size=5][b]5. 总结[/b][/size]
            应该说到目前,我们只是讨论了JBoss ESB一个小的简单的模块,JBoss ESB本身还有更多的功能,比如之前所说的集成模块等等.            所以,如果你想比较完整的了解JBoss ESB,应该是去JBoss ESB的站点,然后去读文档,这里特别推荐.            除此之外, JBoss ESB本身还带有大量的例子.可以通过运行这些例子,更容易的了解JBoss ESB.            如果在用JBoss ESB遇到问题是,可以上[url=http://www.jboss.com/index.html?module=bb&op=viewforum&f=246]JBoss ESB论坛[/url]提问.        
[size=5][b]Bibliography[/b][/size]
[list=1][li][url=http://www.jboss.org/jbossesb/docs/4.4.GA/manuals/html/ProgrammersGuide.html]JBoss ESB Programmers Guide[/url] (强烈推荐)            [/li][li][url=http://www.jboss.org/jbossesb]JBoss ESB website[/url][/li][li][url=http://jbossesb.blogspot.com/]JBoss ESB Blog[/url][/li][li][url=http://www.jboss.org/jbossesb/docs/index.html]JBoss ESB documentation[/url][/li][li][url=http://www.jboss.com/index.html?module=bb&op=viewforum&f=246]JBoss ESB user forum[/url][/li][/list]