JBoss ESB学习笔记2——第一个ESB应用Hello World

续上文搭建好开发环境后就可以开发ESB应用了。本文介绍第一个ESB应用——Hello, World。


说明:本文及后续文章虽非百分百的原创,但毕竟包含本人的努力和付出,所以希望大家转载时务请注明出处:http://yarafa.iteye.com,谢谢合作。

 

 

1. 新建ESB工程
如下两图所示,输入项目名称,选中JBoss ESB Runtime。

JBoss ESB

JBoss ESB

 

 

2. 基本概念介绍
在进行下面的操作之前有必要介绍JBoss ESB的一些基本概念,如果没有这些概念作基础,而仅仅是机械的操作,那是没有意义的。
2.1 Provider
在JBoss ESB中,使用Provider定义来提供ESB对外的入口,常用的Provider有:jms-provider,fs-provider,ftp-provider,schedule-provider,sql-provider,http-provider,jms-jca-provider,jbr-provider等。

2.1.1 jms-provider
用户定义JMS的接口入口,对外发布的接口可以通过JMS的形式提供出去,通过在jboss-esb.xml文件中定义JMS 的Provider,同时定义JMS监听器,就可以从监听器接收到来自客户端的JMS请求。


2.1.2 fs-provider
文件系统的接口入口,可以定义接入的文件目录,文件扩展名等信息,当特定的文件被透过任意途径放到接入目录后,监听fs-provider的监听器就可以接收到消息,并可以读取到文件的内容,文件被处理后,还可以被移动到特定的目录下,也可以修改文件的后缀名以标识文件已经被接口程序处理过了。

 

2.1.3 ftp-provider
FTP入口,可以定义入口FTP服务器的IP,用户名,密码,目录路径等信息。当有文件被上传到定义好的FTP服务器目录时,接口入口对应的监听器就可以监听到文件,并将文件内容通过Message的形式传递给接口程序。这个接口适合于通过FTP和我们系统进行通讯的接口。


2.1.4 sql-provider
数据库表接口。这个Provider适合于表接口程序。外部系统对某一个表的数据库操作可以被对这个Provider进行监听的监听器捕捉到,并调用相关的Action进行处理。

 

2.1.5 http-provider
HTTP方式的接口接入定义,通过http-provider,可以向外提供HTTP形式的接口,并接收来自这个接口的HTTP请求,可以通过请求获取到请求参数。除了通过HTTP接口提供对外接口以外,也可以通过这个接口方式来提供服务集成,我们可以在门户上指定ESB上的HTTP-Provider接口,并通过这个接口去访问外部接口,再将外部接口返回的数据封装成HTML能识别的格式,发送给门户上的Portal,从而实现服务集成。


2.1.6 jbr-provider
通过jbr-provider,可以实现Web Service的接口中介功能。

2.2 Service
Service是JBoss ESB对外发布的服务,一个Service一般包括两个部分,一个是Listener,一个是Action。Listener负责监听客户端接口发起者发送过来的消息,Action负责处理接口请求。一个Service可以有多个Listener,对多个接口入口请求;一个Service也可以有多个Action,不同的Action可以有不同的处理逻辑,也可以通过Router将多个Service组装起来,形成服务链条的形式提供服务。

 

2.3 Listener
Listener是JBoss ESB提供的各类形式的provider的监听器,通过Listener,可以获取客户端发送到Provider上的各类消息。
2.3.1 jms-listener
JMS的监听器,通过jms-listener来监听通过jms-provider进来的消息。


2.3.2 fs-listener
文件系统的监听器,通过fs-listener来监听通过fs-provider进来的消息。


2.3.3 ftp-listener
ftp监听器,通过ftp-listener来监听通过ftp-provider进来的消息。


2.3.4 sql-listener
sql监听器,通过sql-listener监听通过sql-provider进来的消息。


2.3.5 http-gateway
http监听器,监听来自http-provider的消息。
 

2.3.6 udp-listener
udp-listener用来监听指定端口的socket请求,udp-listener相对其他listener比较特殊,他无需定义provider,可以直接通过listener配置来监听指定端口的socket消息。
 

2.4 Action
Action是在Service节点下面配置的,用于相应接口请求。Action可以是我们开发人员开发的继承了AbstractActionLifecycle类的java class,可以在配置中指定process属性,表明这个Action要执行的方法名称,也可以指定exceptionMethod属性,标明当异常出现的时候,要执行的方法名称。除了可以开发Action来处理业务逻辑以外,还可以通过Action来做数据转换,服务路由等。JBoss ESB提供了若干自带的Action。
 

3 Provider定义
在JBoss ESB Editor中,新建JMS Provider,输入名称和连接工厂名称,分别是:JBossMQ和ConnectionFactory。点击下一步,输入通道ID:helloworldChanel。

JBoss ESB

JBoss ESB

 

 

4 定义消息队列
在JBoss ESB Editor中,选中Filter节点,输入目的地名称:queue/helloworld选中目的地类型为QUEUE(队列),之后保存。

JBoss ESB

 

 

5 创建服务
在JBoss ESB Editor中,选中Service节点,新建服务,输入服务名称,类别以及描述信息,Finish即可。回到JBoss ESB Editor,设置invmScope属性为GLOBAL。该这只的具体含义以后会做介绍,这里不做说明。

JBoss ESB

 

 

6 创建JMS Listener
在JBoss ESB Editor中,选中Listener节点,新建JMS Listener,输入监听器的名称,同时选中之前创建的通道的ID。最后在JBoss ESB Editor中设置该监听器的is-gateway属性为true。这使得ESB可以直接处理JMS消息。

 

If you send a message directly to another service internally, it must be an EsbMessage! Only Gateways are capable of receiving real JMS messages..  ——某网友语

 

JBoss ESB

JBoss ESB

 

 

7 Action类定义
由于这里使用的是自定义的action,所以在配置action之前需要编写一个扩展了AbstractActionLifecycle类的action类,类定义如下:

JBoss ESB

 

/***********************************************************************
 * <p>Project Name: helloworld</p>
 * <p>File Name: com.thu.afa.esb.jbossesb.action.HelloWorldAction.java</p>
 * <p>Copyright: Copyright (c) 2010</p>
 * <p>Company: <a href="http://afa.thu.com">http://afa.thu.com</a></p>
 ***********************************************************************/
package com.thu.afa.esb.jbossesb.action;

import org.jboss.soa.esb.actions.AbstractActionLifecycle;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.message.Message;

/**
 * <p>Class Name: HelloWorldAction</p>
 * <p>Description: </p>
 * @author Afa
 * @date 2010-9-6
 * @version 1.0
 */
public class HelloWorldAction extends AbstractActionLifecycle
{
	protected ConfigTree configTree;
	
	public HelloWorldAction(ConfigTree configTree)
	{
		this.configTree = configTree;
	}
	
	public Message doPrintMessage(Message message) throws Exception
	{
		System.out.println(message.getBody().get());
		
		return message;
	}
}

 

Action类说明:在action类中必须有一个ConfigTree类型的属性以及一个包含ConfigTree类型参数的构造方法,而逻辑处理方法(这里是doPrintMessage)的参数和返回值都必须是Message。

 

8 Action配置
在JBoss ESB Editor中,选中Action节点,新建Custom Action,如下图所示,输入名称,类路径,并指定处理方法。到此,ESB工程的配置基本完成,下面可以进行部署了。

JBoss ESB

 

 

9 ESB部署
首先在esbcontent文件夹下新建jbm-queue-service.xml文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<server>
	<mbean code="org.jboss.jms.server.destination.QueueService"
		name="jboss.esb.helloworld.destination:service=Queue,name=helloworld"
		xmbean-dd="xmdesc/Queue-xmbean.xml">
		<depends optional-attribute-name="ServerPeer">
			jboss.messaging:service=ServerPeer
		</depends>
		<depends>jboss.messaging:service=PostOffice</depends>
	</mbean>
</server>

 

然后在esbcontent/META-INF目录下新建deployment.xml文件,内容如下:

<jbossesb-deployment>
	<depends>	jboss.esb.helloworld.destination:service=Queue,name=helloworld
	</depends>
</jbossesb-deployment>

 

将整个工程导出成ESB文件,并将其保存至%JBOSSESB_SERVER_HOME%\server\default\deploy目录下,然后启动ESB服务器。工程文件目录结构如下图所示。

JBoss ESB

 

 

 

10 ESB客户端
新建Java工程,并将以下Jar包添加到classpath(注:所有的Jar包都可以在jboss-esb-server中找到),客户端测试代码如下所示。

JBoss ESB

 

/***********************************************************************
 * <p>Project Name: helloworldclient</p>
 * <p>File Name: com.thu.afa.esb.jbossesb.client.HelloWorldClient.java</p>
 * <p>Copyright: Copyright (c) 2010</p>
 * <p>Company: <a href="http://afa.thu.com">http://afa.thu.com</a></p>
 ***********************************************************************/
package com.thu.afa.esb.jbossesb.client;

import java.util.Properties;

import javax.jms.Message;
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;

/**
 * <p>Class Name: HelloWorldClient</p>
 * <p>Description: </p>
 * @author Afa
 * @date 2010-9-6
 * @version 1.0
 */
public class HelloWorldClient
{
	private QueueConnection connection;
	private QueueSession session;
	private Queue queue;
	
	public void setupConnection() throws Exception
	{
		System.out.println("Connection Starting...");
		
		Properties properties = new Properties();
		properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");   
		properties.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");   
		properties.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099");
		InitialContext context = new InitialContext(properties);
		
		QueueConnectionFactory factory = (QueueConnectionFactory) context.lookup("ConnectionFactory");
		connection = factory.createQueueConnection();
		queue = (Queue) context.lookup("queue/helloworld");
		session = connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
		connection.start();
		
		System.out.println("Connection Started");
	}
	
	public void stop() throws Exception
	{
		if(connection != null) connection.stop();
		if(session != null) session.close();
		if(connection != null) connection.close();
	}
	
	public void sendMessage(String text) throws Exception
	{
		QueueSender sender = session.createSender(queue);
		Message message = session.createTextMessage(text);
		sender.send(message);
		sender.close();
	}
	
	/**
	 * <p>Title: </p>
	 * <p>Method Name: main</p>
	 * <p>Description: </p>
	 * @author: Afa
	 * @date: 2010-9-6
	 * @param args
	 */
	public static void main(String[] args) throws Exception
	{
		HelloWorldClient main = new HelloWorldClient();
		main.setupConnection();
		main.sendMessage("Llu, miss you");
		main.stop();
	}
}

 

运行客户端即可在控制台窗口看到如下信息(下图控制台窗口中最后一行信息):

JBoss ESB

 

 

综上,第一个JBoss ESB实例到此全部完成,包括服务端和客户端。

 

11 注意事项
11.1 JMS Provider配置
在JMS Provider配置中,上述示例中的name属性是JBossMQ, 但是对于JBoss ESB Server来说,是默认使用JBoss Messaging的。如果是把JBoss ESB安装在JBoss AS 4.x的服务器,那么就是用JBoss MQ,因为JBoss AS 4.x默认是使用JBoss MQ。


11.2 Listener的Gateway属性
在listener里,我们通过busidref来关联到我们定义在provider里面的bus。在上述示例中,我们定义了一个listener,并且做为Gateway,只负责从外界获取到JMS消息,然后转成ESB内部所需要的Message。

 

11.3 自定义的Action类
一般来说每个Action都要继承AbstractActionLifecycle类,输入/输出参数都必须是ESB的Message,方法名可以随便定义。你只需要在jboss-esb.xml的action的process属性中写对应的方法名即可。如果不写,默认是process方法。
ConfigTree是个很重要的属性,我们很经常会在Action配置其他的信息,那么,所有的信息都可以通过ConfigTree来获取,比如在某个Action中配置静态路由信息。也正是由于在Action中可以随意的配置自己的信息,这增加了很多的灵活性和扩展性。

 

 

 

-----------------------------------------------------
Stay Hungry, Stay Foolish!
http://yarafa.iteye.com

AfaDec 13rd, 2010-----------------------------------------------------