<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    kapok

    垃圾桶,嘿嘿,我藏的這么深你們還能找到啊,真牛!

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      455 隨筆 :: 0 文章 :: 76 評論 :: 0 Trackbacks

    http://jroller.com/page/habuma/20050715#message_driven_pojos

    Message-Driven POJOs

    In my preparation for a presentation I'll be giving next month, I have been tinkering with Message-driven POJOs as proposed by James Strachan and as implemented in ActiveMQ.

    Message-driven POJOs offer MDB-like functionality to simple JavaBeans. I have found message-driven POJOs to be a compelling alternative to MDBs, especially if you're already a big fan of Spring and are using it to develop your applications. Message-driven POJOs can take advantage of all of the features provided by Spring (such as dependency injection and AOP).

    Although message-driven POJOs aren't exactly new news, I had a hard time finding much information about them online. ActiveMQ's own documentation isn't too bad, but left me with several unanswered questions. As a service to everyone out there who may be searching for more info on message-driven POJOs, I'm writing this article to document what I've learned. I hope you find it useful and maybe it will fill in some of the gaps for you.

    What you'll need

    To get started, here's a summary of the JARs that I used when developing and running the examples:

    • activemq-core-3.1-SNAPSHOT.jar
    • activemq-container-3.1-SNAPSHOT.jar
    • activemq-ra-3.1-SNAPSHOT.jar
    • commons-logging-1.0.3.jar
    • concurrent-1.3.4.jar
    • geronimo-spec-j2ee-connector-1.5-rc4.jar (or equivalent J2EE JAR)
    • geronimo-spec-j2ee-management-1.0-rc4.jar (or equivalent J2EE JAR)
    • geronimo-spec-jms-1.1-rc4.jar (or equivalent J2EE JAR)
    • geronimo-spec-jta-1.0.1B-rc4.jar (or equivalent J2EE JAR)
    • log4j-1.2.9.jar
    • spring.jar (version 1.2.2)

    The biggest challenge you'll face when developing message-driven POJOs is pulling together all of these JARs. To make things easier on you, I've made everything you'll need (including the example code) available here.

    Your mileage may vary if you choose to use different versions of JARs than what I've listed above. One important note, however, is that in my examples, I'm using the shorthand XML available in Spring 1.2, so if you use an older version of Spring, you'll need to tweak the XML appropriately.

    Writing the message-driven POJO

    Writing a message-driven POJO isn't dramatically different than writing a message-driven EJB. The major difference is that you don't have to implement javax.ejb.MessageDrivenBean, which means that you also don't have to implement the EJB lifecycle methods mandated by that interface. (If you need to hook into a POJO's lifecycle, you can use Spring's init-method and destroy-method attributes when declaring the bean.)

    In the interest of keeping the focus on how to develop message-driven POJOs, my example will be as simple as possible. In the grand tradition of all simple examples, here's a "Hello World" message-driven POJO:

      package com.habuma.mdpojo;

      import javax.jms.JMSException;
      import javax.jms.Message;
      import javax.jms.MessageListener;

      public class HelloBean implements MessageListener {
        public void onMessage(Message msg) {
          try {
            String name = msg.getStringProperty("name");
            if(name == null) {
              name = "World";
            }

            System.out.println("Hello " + name + "!");
          } catch (JMSException e) {
            // handle exception?
          }
        }
      }

    Notice that (as with MDBs) message-driven POJOs still must implement javax.jms.MessageListener. Even though James Strachan refers to these as POJOs, I don't consider this a pure POJO because in order to work it must implement a platform/framework-specific interface. But the MessageListener interface isn't too much of a burden to bear and it's still lighterweight than MDBs, so I guess I can't complain too much.

    The onMessage() method should be self-explanatory. When a message is dispatched to this bean, this method is called. Inside of the method, we extract the "name" property from the message and use it to display the traditional greeting.

    Listening for messages

    The next thing to do is to declare HelloBean as a bean in a Spring context and associate it with a message queue. Declaring the bean itself is simple enough (in hello-mdpojo.xml):

      <bean id="helloBean" class="com.habuma.mdpojo.HelloBean"/>

    There's really nothing special about this bean. In a real application, however, your message-driven POJO would probably be more interesting and be injected with references to DAOs, service-layer beans, or some other beans that it collaborates with to do its job. It may also be proxied by some Spring aspects for declarative transactions, security, etc.

    To associate "helloBean" with a message queue, we'll need to use ActiveMQ's JCAContainer. The JCAContainer associates itself with a specific ActiveMQ server and acts as a factory to produce connectors to that server. It is declared in Spring as a <bean>:

      <bean id="activeMQContainer" class="org.activemq.jca.JCAContainer">
        <property name="workManager">
          <bean id="workManager" class="org.activemq.work.SpringWorkManager"/>
        </property>

        <property name="resourceAdapter">
          <bean id="activeMQResourceAdapter"
              class="org.activemq.ra.ActiveMQResourceAdapter">
            <property name="serverUrl" value="tcp://localhost:61616"/>
          </bean>
        </property>
      </bean>

    For the most part, this chunk of XML is boiler-plate code to set up a JCAContainer to interact with the message queue. The good news is that you'll only need one JCAContainer, regardless of how many of your POJOs will be message-driven.

    The only thing of interest is the value assigned to the "serverUrl" property of the "activeMQResourceAdapter" inner-bean. This property tells the container how to connect to your ActiveMQ server--in this case, via TCP on port 61616 of the localhost (where ActiveMQ will be listening by default.)

    At this point we have a JCAContainer that is associated with the ActiveMQ server and we have a POJO that is ready and willing to accept messages. All that's left is to connect the POJO to the JCAContainer. The following <bean> does the trick:

      <bean id="HelloMDP"
          factory-method="addConnector"
          factory-bean="activeMQContainer">
        <property name="activationSpec">
          <bean class="org.activemq.ra.ActiveMQActivationSpec">
            <property name="destination" value="Hello.Queue"/>
            <property name="destinationType" value="javax.jms.Queue"/>
          </bean>
        </property>
        <property name="ref" value="helloBean" />
      </bean>

    This bean is where the proverbial "rubber meets the road". Using Spring's factory-method feature, this bean declaration leans on the JCAContainer's addConnector() method to create a connector to associate the "helloBean" with the ActiveMQ server. Specifically, the "activationSpec" property tells the JCAContainer to set up a connector that listens to the queue named "Hello.Queue" and the "ref" property tells it to send messages from that queue to the bean named "helloBean".

    Bringing this message-driven POJO to life requires two things. First, you'll need to fire up an ActiveMQ server. In the bin directory of the ActiveMQ distribution, you'll find either an activemq.bat (for Windows) or an activemq script (for UNIX). Running this script will start up an ActiveMQ server instance listening on port 61616.

    The next thing you'll need is a simple application that loads the Spring application context. The following main() method should suffice (I'll leave the class you place this in up to you):

      public static void main(String[] args) {
        new FileSystemXmlApplicationContext("hello-mdpojo.xml");
      }

    If all goes well, running this program will result in a HelloBean POJO that is patiently awaiting a message to process. So, let's send it a message.

    Sending a message

    There are a variety of ways to send a JMS message, but for the purposes of this example, I'm going to use Spring's JmsTemplate (as described in chapter 7 of Spring in Action). The following declaration of a JmsTemplate is what I used to test the HelloBean (in mq-client.xml):

      <bean id="jmsTemplate"
          class="org.springframework.jms.core.JmsTemplate">
        <property name="defaultDestinationName" value="Hello.Queue"/>
        <property name="connectionFactory" ref="connectionFactory"/>
      </bean>

    The "defaultDestinationName" property tells the template the name of the message queue to attach to. The "connectionFactory" property tells the template how to connect. I could've used Spring's JndiObjectFactoryBean to pull a connection factory from JNDI (as I described in SiA) or any implementation of javax.jms.ConnectionFactory. But so that I don't have to mess with JNDI for this simple example, let's use ActiveMQ's ActiveMQConnectionFactory:

      <bean id="connectionFactory"
          class="org.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://localhost:61616" />
      </bean>

    Now we just need to use the "jmsTemplate" bean to send a message. In a real application, you might inject "jmsTemplate" into a property of another bean to use. But for simplicity's sake we'll just access the bean directly from a main() method (again, I'll leave the choice of a class up to you):

      public static void main(String[] args) {
        ApplicationContext ctx = new
            FileSystemXmlApplicationContext("mq-client.xml");

        JmsTemplate template = (JmsTemplate) ctx.getBean("jmsTemplate");
        template.send(
          new MessageCreator() {
            public Message createMessage(Session session)
                throws JMSException {
              MapMessage message = session.createMapMessage();
                message.setStringProperty("name", "Craig");
              return message;
            }
          }
        );
      }

    Run this program in a separate window from where the application that runs the JCAContainer. If things are going your way, you should see "Hello Craig!" in the window running the JCAContainer app. Congratulations, you've just invoked a message-driven POJO.

    So what?

    What's the big deal? Why are message-driven POJOs better than MDBs? Well, I never actually claimed any superiority of message-driven POJOs over MDBs. But here are some things to consider:

    • MDBs must be run within an EJB container. Depending on the architecture of your app, this may be an excessive requirement, especially if you aren't use any other EJBs and do not require the features of a full-blown EJB container. Message-driven POJOs, on the other hand, can run anywhere, even (as shown here) in a simple main() method. The only requirement is an ActiveMQ message queue.
    • MDBs require that you implement the lifecycle methods of javax.ejb.MessageDrivenBean. Often these lifecycle methods aren't needed and are left as empty implementations. This isn't a real problem, except that it's simply unnecessary.
    • Although it may not be apparent from the simple HelloBean example, message-driven POJOs can take full advantage of the dependency injection and AOP support offered by Spring (including Spring's support for declarative transactions and Acegi's support for declarative security). In short, you can do anything with the POJO that you can do with any other bean in a Spring context.
    • The XML used to declare a message-driven POJO is slightly more verbose then for an MDB. You should, however, keep in mind that you'll only need to declare one JCAContainer bean, regardless of how many message-driven POJOs your application has.

    One thing that I've not yet considered is how EJB 3 MDBs compare the message-driven POJOs. Honestly, I've not taken the time to perform this comparison. Perhaps this is something I'll do soon. If you have any insight in this subject, I'd be quite interested in hearing it.

    Message-driven POJOs are just a small portion of a talk that I'll be presenting at the LoneStar Software Symposium in Austin, TX next month. If you're in the Austin area, I hope to see you there.

    (Note: Any mistakes, typos, or blatant lies in this post are unintentional. If you spot any problems, let me know so that I can correct them.)

    posted on 2005-07-21 15:05 笨笨 閱讀(509) 評論(0)  編輯  收藏 所屬分類: J2EEALL
    主站蜘蛛池模板: 亚洲va在线va天堂va不卡下载| 国产精品美女久久久免费| 伊人久久大香线蕉亚洲五月天| 免费一本色道久久一区| 久久国产乱子伦精品免费不卡| 人碰人碰人成人免费视频| 亚洲精品动漫免费二区| 亚洲人和日本人jizz| 亚洲一区精品中文字幕| 亚洲国产另类久久久精品黑人| 亚洲AⅤ无码一区二区三区在线| 国内一级一级毛片a免费| 99久久精品日本一区二区免费| 久久国产精品免费专区| 免费黄网站在线观看| 免费久久人人爽人人爽av| 一级毛片aaaaaa视频免费看| 偷自拍亚洲视频在线观看99| 青草久久精品亚洲综合专区| 亚洲人成人网站18禁| 亚洲va久久久久| 亚洲综合小说另类图片动图| 日韩亚洲不卡在线视频中文字幕在线观看| 久久亚洲私人国产精品| 亚洲a一级免费视频| 亚洲AV无码专区国产乱码4SE| 久久99亚洲综合精品首页| 亚洲综合精品网站| 国产亚洲美日韩AV中文字幕无码成人 | 狠狠躁狠狠爱免费视频无码| 人妻巨大乳hd免费看| www.av在线免费观看| 国产免费高清69式视频在线观看| 无码毛片一区二区三区视频免费播放| 高潮毛片无遮挡高清免费视频| 麻豆亚洲AV成人无码久久精品 | 国产精品免费AV片在线观看| 午夜视频在线免费观看| 最近免费字幕中文大全视频| 国产成人精品免费午夜app | 亚洲sm另类一区二区三区|