`
zhouxwyeah
  • 浏览: 20403 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

简述MQ6.0和Weblogic8.1的集成兼谈侦听器的应用

阅读更多
   作为一个非科班出身的程序员,一直不大敢写技术类东西,怕没有深度贻笑大方。最近在坛子里面看到一篇关于利用oracle侦听线程连发送消息
通知处理来实现松耦合的文章,觉得将自己用的产品心得写出来也还不错,可以练练手,同时也让自己受益,毕竟不能让自己太闲了。
   
   其实上面那篇文章是一个典型的触发器的应用,触发器用处非常广,不管是所谓的基于事件的JSF,或者是Swing的listener,都处都是它的影子,基本所有成熟的商业产品都会加入这么一个特性,对于开发中的作用也是挺大的,我下面谈下我开发中用到的MQ简单侦听器应用。

    前年开发的一个银行系统,某银行和人行之间的通信是通过MQ报文进行交互的,而应用服务器的选型是weblogic8.1(太古老了),当时的MQ版本是MQ6.0。这是一个典型的基于消息的应该,就是要求消息一来就要进行相应的处理,当然如果是JMS队列的话,基本上就很简单了,毕竟MDB能够监听它,但是这里是MQ,MQ和WebSphere结合的很好,他可以让MDB监听MQ队列和监听JMS队列一样简单,可以直接配置JMS队列对应MQ队列,但是到了weblogic就不行了,weblogic的JMS队列和MQ是完全没有关系的,也就是说weblogic根本不知道MQ什么时候得到消息,服务器就不能实时的处理业务(该死的厂商不兼容…)。

  (基于这个情况我后来查了一些资料,发现BEA和IBM也给出过解决方案,比较复杂,要配置一堆东西。而且和厂商绑定也是很紧,出错了也不知道找谁,我还是倾向我自己的这个方案,这是后话)。
 
   当时有两个选择: 
  1.轮询MQ对列,有消息就取出来(听着就不大好) 
  2.“想办法让weblogic服务器知道MQ收到消息”
  
   我们倾向第二种,毕竟由消息来通知比较靠谱,而且轮询比较浪费浪费资源,而且能够实时的得到消息,这时我们就注意到MQ的触发器了:

如图:


   这是一个本地队列的属性选项,它有一个触发器选型,我们可以将它打开,我们可以看到它的触发器类型,具体表示:
  第一个(FIRST):当收到第一个消息的时候触发该触发器
  每个(EVERY):每收到一个消息都触发
  深度(DEPTH):可以配置指定深度的消息时候触发该触发器
   触发器被触发的时候会做些什么呢?我们看看还有一个进程名称的输入框(记住我们这里配置为Trigger),也就是说触发器被触发时候会执行该名称的进程
(关于该进程我们在后面会说到)。

脚本如下:
define QLOCAL(QUEUE1)
 put(enable) get(enable) 
 Trigger //表示开通触发器
 PROCESS(Trigger)  //触发进程
 TRIGTYPE(FIRST) //触发器类型为first
 USAGE(NORMAL) 
 INITQ('SYSTEM.DEFAULT.INITIATION.QUEUE') //初始化队列
 REPLACE[/size]


   上面我们提到,我们要想办法让服务器知道MQ收到消息了,利用触发器,我们可以很好的做到这点(当然没有直接配置为JMS队列方便了),方案如下:

首先我们在weblogic配置了一个MDB,让他来监听并且处理MQ队列的消息,这是我们的初衷,前面我们说过weblogic的MDB不能监听MQ,所以利用触发来达到这一点,我们假定监听的连接工厂JNDI为jms/connection,JMS队列为queue,首先我们写一个往MDB侦听的JMS队列发送消息的简单程序:
import java.util.Hashtable;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
public class Trigger {

	public static void main(String[] args) {

		QueueConnection conn = null;

		try {

			Hashtable hash = new Hashtable();

			hash.put(Context.INITIAL_CONTEXT_FACTORY,

				"weblogic.jndi.WLInitialContextFactory");

			hash.put(Context.PROVIDER_URL,"t3://localhost:7001");
			InitialContext ic = new InitialContext(hash);
			QueueConnectionFactory factory =  (QueueConnectionFactory) ic.lookup("jms/connection");
			conn = factory.createQueueConnection();
			QueueSession session = conn.createQueueSession(false,
					Session.AUTO_ACKNOWLEDGE);
			Queue queue = (Queue) ic.lookup("queue");
			QueueSender sender = session.createSender(queue);
			TextMessage message =  session.createTextMessage("Trigger");
			sender.send(message);
		} catch (Exception e) {
			System.out.println(e.getStackTrace());
		} finally {
			if (conn != null) {
			try {
				conn.close();
				} catch (Exception e) {
					System.out.println(e.getStackTrace());
				}
			}
		}

	}

}


   然后我们在服务器上上面编译该java文件   javac Trigger.java,生成 .class文件,然后将该类的路径配置进环境变量。这样我们得到一个发生JMS消息的程序。
   记得我们前面提到过进程定义,这也是MQ的一个特征,如图:



    我们可以在队列管理器的高级-----进程定义------------新建进程定义Trigger,我们可以看到一个应用程序标识框,可以输入命令,即标识该经常定义所做的事情,这里我们定义为java Trigger,即给weblogic的MDB监听的JMS队列发送消息,即该进程定义为支持java Trigger命令。
脚本:
define process(Trigger) appltype(unix) applicid(java Trigger)

  这样,我们的配置就结束了,具体的处理流程是这样的:
  MQ本地队列收到消息-------》触发触发器----------》执行进程定义--------》java Trigger给MDB的JMS对列发送消息-------》weblogic的MDB收到消息,然后去MQ读取报文,这样就实现了MDB能够知道MQ什么时候收到消息,然后针对进行业务处理了。
   这样就实现了weblogic8.1的MDB可以监听MQ队列了,当然了,针对触发器大家还可以做出各种应用,就看具体的需求了。
   (不知道9或者以后的版本weblogic能不能直接监听MQ队列)
    这样也会产生其他的问题,比如MDB的事务就很难保证,还有出了异常的MQ消息的容错处理,毕竟不是JMS对列,J2EE的事务好像加不上去。

   对于触发器(又或者叫侦听器,都是侦听事件然后做出相应的处理),在很多产品都应用,比如DB2的触发器,又或者是WPS流程人工任务的事件处理(这里就不详谈),这也很像我们平时所谈到的pull和push得选择一样,既然很多成熟的产品都选择了这样特性,也说明了它的可取之处,也是push用的比pull多的原因,也许我们在平时开发的过程中加上一点触发器的思想,可能会收到不错的效果。
 
   写的比较乱,如果有错误欢迎大家指出。希望对需要的人有所帮助。
   PS:写完不知道往哪里发,以前的厂商分坛找不到了,只能放这里了。。。。
  • 大小: 21.2 KB
  • 大小: 30.9 KB
分享到:
评论
2 楼 zhouxwyeah 2009-11-12  
shevliu 写道
《Java实时获取oracle变更》这篇文章描述的其实是streams的内容,和触发器还是有一定区别。

至于楼主谈到的MQ与WEBLOGIC集成,不妨试试外部服务器(foreign server)?

外部服务器的这种方式我在后面的项目中也试验过,应该是通过本地JNDI来映射到MQ队列,也还不错。我是通过配置本地JNDI来用axis2的webservice来监听报文请求,MQ的报文也会自动被AXIS2监听到,好像外部服务器的方式更加正规一点,呵呵,我这个只是把触发器和发送报文结合了下,算是歪门邪道了~
1 楼 shevliu 2009-11-12  
《Java实时获取oracle变更》这篇文章描述的其实是streams的内容,和触发器还是有一定区别。

至于楼主谈到的MQ与WEBLOGIC集成,不妨试试外部服务器(foreign server)?

相关推荐

Global site tag (gtag.js) - Google Analytics