Java EE 7:带有Glassfish v4的JMS 2.0

Java EE 7最近已被执行委员会接受 。 这意味着我们很快将在市场上提供Java EE 7应用服务器。 构成Java EE 7的规范之一是JMS 2.0 。 自1.1版以来,引入了一些有趣的改进。

JMS有很多怪异的东西,例如: Connection#createSession(boolean Transacted,int acceptMode)方法。

第一个方法参数( transacted )定义是否应处理会话。 Java EE应用程序具有负责事务处理的JTA。 我们可以选择是否支持交易(默认)。 那么,为什么我们需要这个论点呢?
第二个方法参数( acknowledgeMode )是一个从Session对象获取的整数常量 。 认真地说,整数常量使该API看起来太过传统。 最后,Java EE环境中这些参数的含义是什么? JavaDoc的说, acknowledgeMode如果会话事务被忽略。

这是什么意思? 不外乎: 这些参数对于Java EE上下文中使用的JMS生产者没有任何意义 。 这就是为什么他们鼓励您使用(true, 0)参数值以避免不必要的混淆的原因。 这闻起来有遗味。

好的,让我们回到主要主题。 我想看一下JMS世界中的新功能,以及它如何使我能够更轻松,更可维护的方式进行编码。 我已经准备了一个使用JMS 2.0,JAX-RS和EJB(SLSB和MDB)的简单Web应用程序,并将其推送到这里的 github存储库中。

先决条件和基础架构

为了能够运行此代码,您应该创建一个示例队列。 我已经在jms/queue/myqueue JNDI名称下配置了它。

我正在使用Glassfish v4 build 87 。 要使用Java EE 7 API,我需要添加以下Maven依赖项:

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>7.0-b87</version>
    <scope>provided</scope>
</dependency>

驻留在此存储库中:

<repository>
    <id>Java EE 7</id>
    <url>https://maven.java.net/content/groups/promoted/</url>
</repository>

这就是配置的全部内容。

有效负载和REST配置

BusinessObject是一个简单的对象,将充当我们的JMS消息的有效负载。 它将由生产者发送并由消费者接收。 这里没什么好想的,所以让我们继续前进。 RESTConfiguration甚至更简单–它只是为我们的应用程序定义了JAX-RS端点前缀。 该前缀是:“ / rest”。 您可以通过访问应用程序URL / rest / producer / jms11或/ rest / producer / jms20(例如http://localhost:8080/jms2_0_spike/rest/producer/jms20 )来调用生产者EJB。

JMS生产者

现在,这里开始变得有趣。 在下面,您可以找到SLSB JMS消息产生器的JMS 1.1代码:

@Stateless 
public class JMS11Producer {

    @Resource(lookup = "jms/__defaultConnectionFactory")
    private ConnectionFactory connectionFactory;

    @Resource(lookup = "jms/queue/myqueue")
    private Queue queue;

    @Path("/jms11")
    @GET
    public String produce() {
        String status = "OK";

        Connection connection = null;
        try {
            connection = connectionFactory.createConnection();
            Session session = connection.createSession(true, 0);
            MessageProducer producer = session.createProducer(queue);

            BusinessObject payload = new BusinessObject(UUID.randomUUID().toString());

            ObjectMessage message = session.createObjectMessage();
            message.setObject(payload);

            producer.send(message);
        } catch (JMSException e) {
            status = e.getMessage();
        } finally {
            if (connection != null) {
                try {
                    connection.close();
                } catch (JMSException e) {
                    status = e.getMessage();
                }
            }
        }
        return status;
    }
}

尽管JAX-RS结果状态出现问题,但这是一个令人费解的样板代码,模糊了方法的主要职责。 它应该只向队列发送一条消息,但是它却做了很多事情。 它会创建一个连接,会话(包括讨厌的,忽略的参数在内),对象类型的消息,将其初始化,然后最终将消息发送到队列中……哦,是的–当然,不要忘记检查异常和嵌套的try / catch块。 我们可以尝试去优化它-通过创建连接移动到一些如@PostConstruct方法和关闭,以@PreDestroy -但它仍然有很多unnecesary噪音。

现在,让我们看一下功能上与JMS 2.0中表达的代码相同的代码:

@Stateless 
public class JMS20Producer {

    @Resource(lookup = "jms/queue/myqueue")
    private Queue queue;

    @Inject
    private JMSContext jmsContext;

    @Path("/jms20")
    @GET
    public String produce() {
        BusinessObject payload = new BusinessObject(UUID.randomUUID().toString());

        jmsContext.createProducer().send(queue, payload);

        return "OK";
    }
}

很整洁吧? 弄清楚此方法的作用要容易得多:它创建有效负载并将其发送到队列。 就这样–这就是方法的全部内容。 异常处理,连接和会话创建,消息类型–一切都为我们完成。 如果可以将这些职责转移到容器上以减轻开发人员的生活负担,那么为什么不这样做呢?

让我们看一下此示例中使用的一些JMS 2.0功能:

  • 不需要ConnectionFactory
  • 无需ConnectionSession
  • JMSContext是结合了ConnectionSession功能的新对象。 它可以通过容器注入,
  • 没有检查的异常–仅JMSRuntimeException
  • 用于消息生成的链调用使其更易于阅读。

JMS消费者

自JMS 1.1以来,Message Consumer并未发生太大变化。 它仍然是MDB,但是现在由于使用message.getBody(Clazz)进行消息投射,更容易达到预期的有效负载:

@MessageDriven(mappedName = "jms/queue/myqueue") 
public class Consumer implements MessageListener {

    @Override
    public void onMessage(Message message) {
        try {
            // In JMS 1.1:
            //          ObjectMessage objectMessage = (ObjectMessage)message;
            //          BusinessObject payload = (BusinessObject)objectMessage.getObject();
            BusinessObject payload = message.getBody(BusinessObject.class);
            System.out.println("Message received: " + payload);
        } catch (JMSException e) {
            System.err.println("Error while fetching message payload: " + e.getMessage());
        }
    }
}

结论

这只是对JMS 2.0的快速浏览。 但是,我发现有趣的是,与JMS 1.1相比,可以产生多少更清晰的代码。 有关JMS 2.0的更多详细信息,请查看其正式规范


翻译自: https://www.javacodegeeks.com/2013/05/java-ee-7-jms-2-0-with-glassfish-v4.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值