`
yarafa
  • 浏览: 86887 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

Afa
Dec 13rd, 2010
-----------------------------------------------------

 

 

分享到:
评论
20 楼 qianyang 2013-05-01  
ligenhang 写道
我部署也报
java.lang.RuntimeException: org.jboss.soa.esb.ConfigurationException: The base Listener config [helloworldListener] must reference a base Bus config type (<bus>).
错误


我找到原因了,在配置Listener时没有选择jms Listener,正确的应该是这样:
<jms-listener busidref="helloworldChanel" is-gateway="true" name="helloListener"/>
各位可以查一下
19 楼 hone033 2012-11-13  
已找到原因了
18 楼 hone033 2012-11-13  
DEPLOYMENTS IN ERROR:
  Deployment "jboss.esb.vfszip:/opt/jboss-5.1.0.GA/server/all/deploy/HelloWorld.esb/" is in error due to the following reason(s): javax.jms.JMSException: There is no administratively defined queue with name:queue/helloworld

at org.jboss.deployers.plugins.deployers.DeployersImpl.checkComplete(DeployersImpl.java:993)
at org.jboss.deployers.plugins.deployers.DeployersImpl.checkComplete(DeployersImpl.java:939)
at org.jboss.deployers.plugins.main.MainDeployerImpl.checkComplete(MainDeployerImpl.java:873)
at org.jboss.system.server.profileservice.repository.MainDeployerAdapter.checkComplete(MainDeployerAdapter.java:128)
at org.jboss.system.server.profileservice.hotdeploy.HDScanner.scan(HDScanner.java:369)
at org.jboss.system.server.profileservice.hotdeploy.HDScanner.run(HDScanner.java:255)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:204)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)

这个是怎么回事?为啥会报这个错的,请求帮助
谢谢
17 楼 yarafa 2012-10-27  
feng888918 写道
求一个 jboss esb学习笔记中 客户端 所需 jar  包  非常感谢
邮箱1024784402@qq.com

我在文章中已经说清楚了,所有的jar包都可以在jboss-esb-server中找到,不知道你还需要什么,如果真找不到,你可以从网上下的
16 楼 feng888918 2012-10-13  
求一个 jboss esb学习笔记中 客户端 所需 jar  包  非常感谢
邮箱1024784402@qq.com
15 楼 feng888918 2012-10-12  
求一个 客户端 的 所需 jar   哥哥们  我的 邮箱1024784402@qq.com
14 楼 xiao_2008 2012-07-30  
very good.
13 楼 huangpoyuan 2012-03-09  
Exception in thread "main" javax.naming.NameNotFoundException: helloworld not bound
at org.jnp.server.NamingServer.getBinding(NamingServer.java:771)
at org.jnp.server.NamingServer.getBinding(NamingServer.java:779)
at org.jnp.server.NamingServer.getObject(NamingServer.java:785)
at org.jnp.server.NamingServer.lookup(NamingServer.java:443)
at org.jnp.server.NamingServer.lookup(NamingServer.java:399)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:305)
at sun.rmi.transport.Transport$1.run(Transport.java:159)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:142)
at org.jnp.server.NamingServer_Stub.lookup(Unknown Source)
at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:728)
at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:688)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at com.thu.afa.esb.jbossesb.client.HelloWorldClient.setupConnection(HelloWorldClient.java:32)
at com.thu.afa.esb.jbossesb.client.HelloWorldClient.main(HelloWorldClient.java:58)

我按例子做的,提示helloworld not bound,这是什么原因?
12 楼 nitian123ok 2011-12-01  
java.lang.RuntimeException: org.jboss.soa.esb.ConfigurationException: The base Listener config [helloworldListener] must reference a base Bus config type (<bus>).
Exception in thread "main" org.jboss.jms.exception.MessagingJMSException: Failed to invoke
at org.jboss.jms.client.delegate.DelegateSupport.handleThrowable(DelegateSupport.java:271)
at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate.org$jboss$jms$client$delegate$ClientConnectionFactoryDelegate$createConnectionDelegate$aop(ClientConnectionFactoryDelegate.java:198)
at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate$createConnectionDelegate_N3019492359065420858.invokeNext(ClientConnectionFactoryDelegate$createConnectionDelegate_N3019492359065420858.java)
at org.jboss.jms.client.container.StateCreationAspect.handleCreateConnectionDelegate(StateCreationAspect.java:80)
at org.jboss.aop.advice.org.jboss.jms.client.container.StateCreationAspect0.invoke(StateCreationAspect0.java)

运行客户端时报的异常。还请楼主帮忙!
at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate$createConnectionDelegate_N3019492359065420858.invokeNext(ClientConnectionFactoryDelegate$createConnectionDelegate_N3019492359065420858.java)
at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate.createConnectionDelegate(ClientConnectionFactoryDelegate.java)
at org.jboss.jms.client.JBossConnectionFactory.createConnectionInternal(JBossConnectionFactory.java:205)
at org.jboss.jms.client.JBossConnectionFactory.createQueueConnection(JBossConnectionFactory.java:101)
at org.jboss.jms.client.JBossConnectionFactory.createQueueConnection(JBossConnectionFactory.java:95)
at com.thu.afa.esb.jbossesb.client.HelloWorldClient.setupConnection(HelloWorldClient.java:50)
at com.thu.afa.esb.jbossesb.client.HelloWorldClient.main(HelloWorldClient.java:92)
Caused by: java.lang.NoSuchMethodError: org.jboss.remoting.Client.connect(Lorg/jboss/remoting/ConnectionListener;Ljava/util/Map;)V
at org.jboss.jms.client.remoting.JMSRemotingConnection$1.run(JMSRemotingConnection.java:374)
at java.security.AccessController.doPrivileged(Native Method)
at org.jboss.jms.client.remoting.JMSRemotingConnection.start(JMSRemotingConnection.java:368)
at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate.org$jboss$jms$client$delegate$ClientConnectionFactoryDelegate$createConnectionDelegate$aop(ClientConnectionFactoryDelegate.java:165)
... 10 more
11 楼 ligenhang 2011-10-13  
我部署也报
java.lang.RuntimeException: org.jboss.soa.esb.ConfigurationException: The base Listener config [helloworldListener] must reference a base Bus config type (<bus>).
错误
10 楼 wh3577 2011-09-28  
部署helloworld发生错误:
引用
java.lang.RuntimeException: org.jboss.soa.esb.ConfigurationException: The base Listener config [helloworldListener] must reference a base Bus config type (<bus>).

求版主解释!先谢谢了啊!我邮箱是wh3577@163.com,求交流!哈哈
9 楼 wh3577 2011-09-28  
部署helloworld发生错误:
引用
java.lang.RuntimeException: org.jboss.soa.esb.ConfigurationException: The base Listener config [helloworldListener] must reference a base Bus config type (<bus>).

求版主解释!先谢谢了啊!
8 楼 yarafa 2011-08-30  
deployment.xml是一个依赖文件,即启动本esb工程需要依赖的一些服务或者消息队列
7 楼 hesihua 2011-08-11  
还有就是deployment.xml这个是干什么用的?
6 楼 crabboy 2011-04-29  
终于通了:s-gateway属性为true
service的invmScope属性为GLOBAL

至于为什么,就不得而知了。留着以后再消化
5 楼 yarafa 2011-04-25  
这句话说的很清楚,
Service configuration for Service 'HelloWorld:HelloWorldService' doesn't define a Message-Aware Listener
你没有设置一个is-gateway属性为false的listener,用于传递经ESB封装后的消息,此时需要设置service的invmScope属性为GLOBAL
4 楼 yarafa 2011-04-25  
你的service是否设置了invmScope属性为GLOBAL
3 楼 crabboy 2011-04-24  
引用

--- MBeans waiting for other MBeans ---
ObjectName: jboss.esb:deployment=helloworld.esb
  State: FAILED
  Reason: java.lang.RuntimeException: org.jboss.soa.esb.ConfigurationException: Service configuration for Service 'HelloWorld:HelloWorldService' doesn't define a Message-Aware Listener (i.e. is-gateway='false').
  I Depend On:
    jboss.esb:deployment=jbossesb.esb
    jboss.esb.helloworld.destination:service=Queue,name=helloworld

--- MBEANS THAT ARE THE ROOT CAUSE OF THE PROBLEM ---
ObjectName: jboss.esb:deployment=helloworld.esb
  State: FAILED
  Reason: java.lang.RuntimeException: org.jboss.soa.esb.ConfigurationException: Service configuration for Service 'HelloWorld:HelloWorldService' doesn't define a Message-Aware Listener (i.e. is-gateway='false').
  I Depend On:
    jboss.esb:deployment=jbossesb.esb
    jboss.esb.helloworld.destination:service=Queue,name=helloworld

照着做了几遍还是这样的错误,求解!
2 楼 crabboy 2011-04-24  
部署helloworld发生错误:
引用
java.lang.RuntimeException: org.jboss.soa.esb.ConfigurationException: The base Listener config [helloworldListener] must reference a base Bus config type (<bus>).
1 楼 crabboy 2011-04-24  
奇怪了,我在
引用
6 创建JMS Listener
的时候,没有看到
引用
设置该监听器的is-gateway属性
这个按钮啊?版本不对?

相关推荐

Global site tag (gtag.js) - Google Analytics