Apache TomEE + JMS。 从未如此简单。

我记得J2EE (1.3和1.4)的过去,使用JMS启动项目非常困难。 您需要安装JMS代理,创建主题队列,最后使用服务器配置文件和JNDI开始自己的战斗。

感谢JavaEE 6及其它,使用JMS确实非常简单。 但是,使用Apache TomEE更加容易上手。 在本文中,我们将了解如何创建和测试一个简单的应用程序,该应用程序使用Apache TomEEJMS队列发送消息或从JMS队列接收消息。

Apache TomEE使用Apache Active MQ作为JMS提供程序。 在此示例中,您不需要下载或安装任何东西,因为所有元素都将作为Maven依赖项提供,但是如果您计划(并且应该)使用Apache TomEE服务器,则需要下载Apache TomEE plus或Apache TomEE plume。 您可以在http://tomee.apache.org/comparison.html中了解有关Apache TomEE风味的更多信息。

依存关系

首先要做的是添加javaee-api作为提供的依赖关系,并添加junitopenejb-core作为测试依赖关系。 请注意,添加了openejb-core依赖项以具有运行时来执行测试,我们将在测试部分中对其进行深入了解。

<dependencies>
  <dependency>
    <groupId>org.apache.openejb</groupId>
    <artifactId>javaee-api</artifactId>
    <version>6.0-6</version>
    <scope>provided</scope>
  </dependency>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.apache.openejb</groupId>
    <artifactId>openejb-core</artifactId>
    <version>4.7.1</version>
    <scope>test</scope>
  </dependency>
</dependencies>

商业代码

下一步是创建负责发送消息和从JMS队列接收消息的业务代码。 它还包含一种从队列接收消息的方法。 对于此示例,我们将使用无状态EJB

import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

@Stateless
public class Messages {

  //Standard @Resource annotation is used to inject the ConnectionFactory. 
  //If no name is provided using lookup or name attribute, 
  //the fully qualified name of the class with an slash (/) and the name of the attribute is used. 
  //In this example: java:comp/env/org.superbiz.jms.Messages/connectionFactory.
  @Resource 
  private ConnectionFactory connectionFactory;

  //Standard @Resource annotation is used to inject the Queue. 
  //If no name is provided using lookup or name attribute, 
  //the fully qualified name of the class with an slash (/) and the name of the attribute is used. 
  //In this example: java:comp/env/org.superbiz.injection.jms.Messages/chatQueue.
  @Resource 
  private Queue chatQueue;


  public void sendMessage(String text) throws JMSException {

      Connection connection = null;
      Session session = null;

      try {
          connection = connectionFactory.createConnection();
          //Connection is get from ConnectionFactory instance and it is started.
          connection.start(); 

          //Creates a session to created connection.
          session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); 

          //Creates a MessageProducer from Session to the Queue.
          MessageProducer producer = session.createProducer(chatQueue);
          producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); 

          TextMessage message = session.createTextMessage(text);

          //Tells the producer to send the message
          producer.send(message); 
      } finally {
          if (session != null) session.close(); 
          if (connection != null) connection.close();
      }
  }

  public String receiveMessage() throws JMSException {

      Connection connection = null;
      Session session = null;
      MessageConsumer consumer = null;

      try {
          connection = connectionFactory.createConnection();
          connection.start();

          session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

          consumer = session.createConsumer(chatQueue); 

          //Waits for a message with timeout. Note that because a TextMessage is sent, the receive method expects a TextMessage too.
          TextMessage message = (TextMessage) consumer.receive(1000); 

          return message.getText(); 
      } finally {
          if (consumer != null) consumer.close();
          if (session != null) session.close();
          if (connection != null) connection.close();
      }
  }
}

Messages类最重要的部分是注意注入ConnectionFactory和在代码内将实例排队。 您只需要使用@Resource批注,容器将为您完成其余的工作。 最后请注意,由于我们尚未使用namelookup属性来设置名称,因此将字段名称用作资源名称。

测试

最后,我们可以编写一个测试来断言使用JMS队列发送和接收消息。 例如,我们可以使用Arquilian编写测试,但是由于这种情况,由于简单起见,我们将使用嵌入式OpenEJB实例来部署JMS示例并运行测试。

public class MessagesTest {

  //Messages EJB is injected.
  @EJB
  private Messages messages;

  @Before
  public void setUp() throws Exception {
    Properties p = new Properties();
    //Embedded OpenEJB container is started.
    //And current test added inside created container
    //So we can use javaee annotations inside
    EJBContainer.createEJBContainer(p).getContext().bind("inject", this); 
  }

  @Test
  public void shouldSendAndReceiveMessages() throws Exception {

    //Three messages are sent.
    messages.sendMessage("Hello World!"); 
    messages.sendMessage("How are you?");
    messages.sendMessage("Still spinning?");

    //Three messages are received.
    assertThat(messages.receiveMessage(), is("Hello World!")); 
    assertThat(messages.receiveMessage(), is("How are you?"));
    assertThat(messages.receiveMessage(), is("Still spinning?"));
  }

}

请注意,该测试非常简单明了,您只需要以编程方式启动EJB容器并在其中绑定当前测试,因此我们可以在测试中使用JavaEE注释。 其余的是一个简单的JUnit测试。

而且,如果您运行测试,您将收到绿色的子弹。 但是,等等,您可能想知道JMS代理及其配置在哪里? ConnectionFactoryJMS队列的定义在哪里? 这就是OpenEJB (和Apache TomEE )发挥作用的地方。

在这种情况下, OpenEJB (和Apache TomEE )将以嵌入式模式使用Apache Active MQ ,因此您无需在计算机上安装Apache Active MQ即可运行测试。 此外, Apache TomEE将为您创建所有必需的资源。 例如,它将为您创建一个ConnectionFactory和一个带有默认参数和期望名称的队列( org.superbiz.Messages / connectionFactory用于ConnectionFactoryorg.superbiz.Messages / chatQueue用于队列),因此您不必担心在测试阶段配置JMSApache TomEE足够聪明,可以为您创建和配置它们。

您可以通过阅读下一条日志消息来检查控制台输出,以了解资源是自动创建的: INFO:自动创建资源

Jan 10, 2015 10:32:48 AM org.apache.openejb.config.AutoConfig processResourceRef
INFO: Auto-linking resource-ref 'java:comp/env/org.superbiz.Messages/connectionFactory' in bean Messages to Resource(id=Default JMS Connection Factory)
Jan 10, 2015 10:32:48 AM org.apache.openejb.config.ConfigurationFactory configureService
INFO: Configuring Service(id=org.superbiz.Messages/chatQueue, type=Resource, provider-id=Default Queue)
Jan 10, 2015 10:32:48 AM org.apache.openejb.config.AutoConfig logAutoCreateResource
INFO: Auto-creating a Resource with id 'org.superbiz.Messages/chatQueue' of type 'javax.jms.Queue for 'Messages'.
Jan 10, 2015 10:32:48 AM org.apache.openejb.assembler.classic.Assembler createRecipe
INFO: Creating Resource(id=org.superbiz.Messages/chatQueue)
Jan 10, 2015 10:32:48 AM org.apache.openejb.config.AutoConfig processResourceEnvRef
INFO: Auto-linking resource-env-ref 'java:comp/env/org.superbiz.Messages/chatQueue' in bean Messages to Resource(id=org.superbiz.Messages/chatQueue)
Jan 10, 2015 10:32:48 AM org.apache.openejb.config.ConfigurationFactory configureService
INFO: Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
Jan 10, 2015 10:32:48 AM org.apache.openejb.config.AutoConfig createContainer
INFO: Auto-creating a container for bean javaee.MessagesTest: Container(type=MANAGED, id=Default Managed Container)

如此,借助Java EETomEEJMS真的非常简单易上手。 在下一篇文章中,我们将看到如何使用消息驱动Bean (MDB)进行相同的操作。

翻译自: https://www.javacodegeeks.com/2015/01/apache-tomee-jms-it-has-never-been-so-easy.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值