EGL中一种消息传递的解决方案

EGL中一种消息传递的解决方案

                                作者:余朋飞

背景

       许多Web2.0应用程序都需要一种机制来在彼此之间传递和交换消息。在大部分开发环境中,程序员一般都会选择消息队列(Message Queue,MQ)来作为消息交互的底层技术支持。

       EGL是EnterpriseGeneration Language(企业生成语言)的英文缩写,这是一种面向业务的第四代语言。利用EGL可以快速开发和部署Java、COBOL以及Web2.0应用程序。EGL的集成开发环境有IBM Rational Business Developer(RBD)和Eclipse EGL Development Tools(EDT)。读者可以通过访问http://www-01.ibm.com/software/awdtools/developer/business/index.html来了解和下载RBD的试用版。

        在这篇文章中,我们会介绍一种新的可用于EGL语言中的消息传递机制,它使用WebShpere MQ Bridge for HTTP作为传输介质,通过HTTP协议来传递消息。


解决方案

1. WebShpere MQ Bridge for HTTP的介绍

       WebShpere MQ Bridge for HTTP使得客户端应用程序可以互相交换消息,这些客户端程序可以是基于不同的平台或语言,只需要通过HTTP协议,而对WebSphereMQ的客户端不作要求。


图1WebShpere MQ Bridge for HTTP的架构

如图1所示,WebSphereMQ Bridge for由一个J2EE Servlet组成,它通过一个资源适配器来连接到WebSphere MQ。该J2EE Servlet具备处理三种不同类型的HTTP请求的能力:POST、GET和DELETE。

        读者如果想获取更多关于WebSphereMQ Bridge for HTTP的资料,可以访问http://www-01.ibm.com/software/integration/wmq/httpbridge/。

 

2. 联合EGL和WebShpereMQ Bridge for HTTP

        图2所示的框架描述的是我们提出的一种解决方案,它允许EGL语言通过HTTP协议来访问和交换外部消息,以及在Web2.0应用程序内部通过EGL的消息总线(InfoBus)来传递内部消息。

                                      

 图2EGL消息传递的解决方案

在该解决方案的例子中,我们定义了两个消息实体:事件(Event)和聊天(Chat)。事件是指在HTTP客户端中发生的实时事件,而聊天则指用户在分布式环境中互相交谈的机制。在该解决方案中,它们的工作机制是一样的,我们假设这样一种应用场景:

        Web2.0应用程序的用户“Tom”在他的主页上发布了一条状态:Hello EGL,然后EGL的Rich UI Handler将该消息发布到消息总线上。在消息总线上,我们已经订阅了和发布一致的主题,并且具有一个回调函数用于处理接受到的消息。当消息到达消息总线时,回调函数开始被调用,然后EventScanner将通过HTTP协议该消息投递到WebShpere MQ Bridge for HTTP。而WebShpere MQ Bridge for HTTP紧接着将该消息传递到相应的消息队列。

        另一个Web2.0用户“Paul”已经登陆了他的主页。EventScanner每隔一秒种将通过HTTP协议,用“拉”的模式来获取消息。当Tom发布的消息“HelloEGL”到达时,就会被投递到消息总线上,然后EGL Rich UI Handler就会将该消息展示在Paul的主页上。


实现方案

 

1. 设置WebShpere MQ Bridge for HTTP环境

      首先在WebSphereApplication Server中创建一个带有WebSphere MQ messaging provider的连接工厂(Connection Factory)。想获取更多关于如何安装和配置WebShpere MQ Bridge for HTTP,读者可以访问http://www-01.ibm.com/support/docview.wss?rs=171&uid=swg24016142&loc=en_US&cs=utf-8?=en&wv=1来下载最新的安装指南和安装包。

       在部署完WebShpereMQ Bridge for HTTP以后,启动WebSphere MQ Explorer,打开“MQ Explorer-Navigator”视图,创建一个队列管理器(QueueManager),命名为“HTTPQM”。如图3和图4所示。


图3创建队列管理器a



图4创建队列管理器b

  保留其他参数为默认值,然后完成该向导,队列管理器“HTTPQM”就创建成功了。  最后,创建如图5和图6所示的本地队列(LocalQueue)。


图5创建本地消息队列a



图6创建本地消息队列b


2. 用EGL开发Web2.0应用程序

        在这个章节中,我们用EGL语言和RBD集成开发环境来开发一个叫做“RBD Team Hub”的Web2.0应用程序,如图7所示。请注意在这篇文章中我们不会说明这个Web应用的所有组件,而是仅关心消息传递的模块,因为这个模块提供了重要的底层消息支持,其他的功能都是在这基础上开发的,这是我们描述的重点。


图7利用EGL/RBD来开发Web2.0应用

以下是消息传递组件的一些EGL代码片段:


  • Event Scanner

library EventScannerLib type BasicLibrary{}

    oldMessage string = "";
    sendmessage string = "";

    function scan()
        Infobus.subscribe("com.ibm.egl.hub.event.send", callback);
        new Job{runFunction = getMessage}.repeat(1000);
    end

    function callback(name string in, data any in)
        sendmessage = data as string;
        serv IRest{@RestBinding{}};
        call serv.invokeDelete("http://localhost:9080/mq/msg/queue/EVENTDELETE",
                sendmessage) returning to invokeDeleteCallback
                onException handlerExcep;
    end

    function getMessage()
        serv IRest{@RestBinding{}};
        call serv.invokeGet("http://localhost:9080/mq/msg/queue/EVENTGET")
                returning to invokeGetCallback onException handlerExcep;
    end

    function invokeGetCallback(message string in)
        if(message != oldMessage)
            Infobus.publish("com.ibm.egl.hub.event.recieve", message);
        end
        oldMessage = message;
    end

    function invokeDeleteCallback(message string in)
        serv IRest{@RestBinding{}};
        call serv.invokePost("http://localhost:9080/mq/msg/queue/EVENTPOST",
                sendmessage) returning to invokePostCallback
                onException handlerExcep;
    end

    function invokePostCallback(sendMesage string in)
    // TODO
    end

    function handlerExcep(e AnyException in)
    // TODO
    end
end


  • Chat Scanner

library ChatScannerLib type BasicLibrary{}

    oldMessage string = "";

    function scan()
        Infobus.subscribe("com.ibm.egl.hub.chat.send", callback);
        new Job{runFunction = getMessage}.repeat(1000);
    end

    function callback(name string in, data any in)
        sendmessage string = data as string;
        destInternetId string = clip(sendMessage[21 : 40]);
        atIndex int = strLib.indexOf(destInternetId, "@");
        destQueue string = destInternetId[1 : atIndex - 1];
        serv IRest{@RestBinding{}};
        call serv.invokePost("http://localhost:9080/mq/msg/queue/" +
                        destQueue, sendmessage) returning to invokePostCallback
                onException handlerExcep;
    end

    function getMessage()
        myInternet string = RbdMemberScannerLib.myInternetId;
        atIndex int = strLib.indexOf(myInternet, "@");
        myQueue string = myInternet[1 : atIndex - 1];
        msg string;
        serv IRest{@RestBinding{}};
        call serv.invokeDelete("http://localhost:9080/mq/msg/queue/" +
                        myQueue, msg) returning to invokeDeleteCallback
                onException handlerExcep;
    end

    function invokeDeleteCallback(message string in)
        if(message != oldMessage && message != "")
            srcInternetId string = clip(message[1 : 20]);
            destInternetId string = clip(message[21 : 40]);
            rbdMember RbdMember = RbdMemberScannerLib.getRbdMemeberByInternet(srcInternetId);
            if(rbdMember != null)
                ChatDialogLib.setUserName(rbdMember.name);
                ChatDialogLib.setPhoto(rbdMember.photo);
            end
            messageBody string = clip(message[41 : strLib.characterLen(message)]);
            chatHistory string = rbdMember.chatHistory + rbdMember.internetid +
                            ": " + messageBody + "
"; RbdMemberScannerLib.setChatHistory(destInternetId, chatHistory); ChatDialogLib.setChatHistory(rbdMember.chatHistory); ChatDialogLib.showChat(); end end function invokePostCallback(sendMesage string in) // TODO end function handlerExcep(e AnyException in) // TODO end end


  • EGL消息总线(InfoBus)

和消息相关的消息总线主题如表1所示:

Topic

Publisher

Subscriber

com.ibm.egl.hub.event.send

UserDetail

EventScannerLib

com.ibm.egl.hub.event.recieve

EventScannerLib

WorkBench

com.ibm.egl.hub.chat.send

ChatDialogLib

ChatScannerLib

                                          表1消息总线主题


样例

 

       为了使该样例能够成功运行,我们建议读者下载该样例并运行。首先利用可视化编辑器(Visual Editor)来打开MainHandler.egl,或者将该应用程序项目部署到应用服务器上,然后在外部浏览器中运行。

 

       需要说明一下在该样例中的用户名列表,读者可以任意选择其中的一个用户名登录应用程序,相应的密码都是“password”。如图8所示.

[email protected]

[email protected]

[email protected]

[email protected]

[email protected]


图8登录对话框

点击“Login”按钮,系统会通过dedicatedservice来校验用户名和密码,一旦授权通过,就会进入用户主页面。

       在这个场景中,假设有两个用户在使用该应用程序:Tom和Paul。让我们来看一下事件(Event)和聊天(Chat)组件是如何工作的。

 

  • 主页中的事件

      如图9所示,用户“Tom”发布了一条最新的状态“Hello EGL!”,然后我们在Paul的主页上的消息面板上看到了这条最新状态“Tom PublishedLatest Status:Hello EGL!”


图9主页中的事件

  • 主页中的聊天功能

       用户“Tom”在好友列表中通过点击“Paul”的头像,发起聊天会话,这样两用户之间可以在弹出的对话框中进行即时交谈。图10所示的是Tom与Paul之间的聊天消息历史。


图10主页中的聊天功能

总结

 

        EGL支持许多和其他遗留系统之间通讯的方式,如数据库、消息队列、服务提供者,等等。用户可以使用SOAP/RESTful服务来消耗或提供Web服务,从而构建基于SOA的Web2.0应用。企业服务总线(EnterpriseService Bus,ESB)和消息队列(MessageQueue,MQ)都可以被快速集成到EGL应用程序中,甚至不用写一行代码。

        简而言之,EGL具有灵活且高扩展性的机制,来允许用户在Web2.0应用程序中来定义自己的框架或解决方案。









你可能感兴趣的:(string,returning,function,websphere,callback,聊天)