在如何使用JMS资源以及在注释上activationConfig使用适当的设置方面似乎存在一些不一致之处。@ActivationConfigProperty``@MessageDriven
activationConfig
@ActivationConfigProperty``@MessageDriven
首先,这是我的资源配置( glassfish-resources.xml ,但可以翻译为其他部署描述符)。这asadmin add- resources glassfish- resources.xml与ActiveMQ资源适配器一起应用于Glassfish():
asadmin add- resources glassfish- resources.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd"> <resources> <resource-adapter-config name="activemq-rar" thread-pool-ids="thread-pool-1" resource-adapter-name="activemq-rar"> <property name="ServerUrl" value="tcp://localhost:61616"/> <property name="UserName" value="admin"/> <property name="Password" value="admin"/> <property name="UseInboundSession" value="false"/> </resource-adapter-config> <admin-object-resource enabled="true" jndi-name="jms/queue/myApp" object-type="user" res-adapter="activemq-rar" res-type="javax.jms.Queue"> <description>MyApp JMS Queue</description> <property name="Name" value="myAppAMQ"/> <property name="PhysicalName" value="myAppAMQ"/> </admin-object-resource> <connector-resource enabled="true" jndi-name="jms/factory/myApp" object-type="user" pool-name="jms/factoryPool/myApp"> <description>MyApp Connection Factory</description> <property name="Name" value="myAppFactory"/> </connector-resource> <connector-connection-pool associate-with-thread="false" connection-creation-retry-attempts="0" connection-creation-retry-interval-in-seconds="10" connection-definition-name="javax.jms.QueueConnectionFactory" connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0" fail-all-connections="false" idle-timeout-in-seconds="300" is-connection-validation-required="false" lazy-connection-association="false" lazy-connection-enlistment="false" match-connections="true" max-connection-usage-count="0" max-pool-size="32" max-wait-time-in-millis="60000" name="jms/factoryPool/myApp" ping="false" pool-resize-quantity="2" pooling="true" resource-adapter-name="activemq-rar" steady-pool-size="8" validate-atmost-once-period-in-seconds="0"/> </resources>
这是我的消息提供程序bean。您会注意到找到了JNDI名称,并且使用了ActiveMQ资源而没有错误,该消息已发送到适当的队列:
@Stateless @LocalBean public class ServicesHandlerBean { @Resource(mappedName = "jms/queue/myApp") private Queue queue; @Resource(mappedName = "jms/factory/myApp") private ConnectionFactory factory; public void sendJMSMessage(MessageConfig messageData) throws JMSException { Connection connection = null; Session session = null; try { connection = factory.createConnection(); session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer messageProducer = session.createProducer(queue); messageProducer.send(createJMSMessage(session, messageData)); } finally { if (session != null) { try { session.close(); } catch (JMSException e) { Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Cannot close session", e); } } if (connection != null) { connection.close(); } } } }
当定义一个 @MessageDriven bean 时,混乱就开始了。以下使用 mapedName的对象 将引发异常:
@MessageDriven(mappedName = "jms/queue/myApp") public class MessageBean implements MessageListener
警告:RAR8000:类setorg中没有方法setName:org.apache.activemq.command.ActiveMQQueue警告:RAR7097:类org.apache.activemq.command.ActiveMQQueue中的属性Name没有设置方法信息:正在访问未访问的引用信息:访问未访问的引用警告:RAR8501:ra的端点激活期间发生异常[activemq- rar],activationSpecClass [org.apache.activemq.ra.ActiveMQActivationSpec]:javax.resource.ResourceException:未知的目标类型:null严重:MDB00017 :[InvoiceProductionMessageBean]:创建消息驱动的bean容器时发生异常:[java.lang.Exception]严重:java.lang.Exception
我被迫这样定义我的MDB:
@MessageDriven( activationConfig = { @ActivationConfigProperty(propertyName = "connectionFactoryLookup", propertyValue = "jms/factory/myApp"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "myAppAMQ"), @ActivationConfigProperty(propertyName = "messageSelector", propertyValue = " JMSType = 'TypeA' "), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") } ) public class MessageBean implements MessageListener
并且我需要提供一个 glassfish-ejb-jar.xml 告诉容器使用ActiveMQ资源,否则我得到一个java.lang.ClassCastException:
java.lang.ClassCastException
警告:RAR8501:ra [jmsra],activationSpecClass [com.sun.messaging.jms.ra.ActivationSpec]的端点激活期间的异常:java.lang.ClassCastException:org.apache.activemq.ra.ActiveMQConnectionFactory无法转换为com。 sun.messaging.jms.ra.DirectConnectionFactory严重:MDB00017:[MessageBean]:创建消息驱动的bean容器时发生异常:[java.lang.Exception]严重:java.lang.Exception
glassfish-ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE glassfish-ejb-jar PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 EJB 3.1//EN" "http://glassfish.org/dtds/glassfish-ejb-jar_3_1-1.dtd"> <glassfish-ejb-jar> <enterprise-beans> <ejb> <ejb-name>MessageBean</ejb-name> <mdb-resource-adapter> <resource-adapter-mid>activemq-rar</resource-adapter-mid> </mdb-resource-adapter> </ejb> </enterprise-beans> </glassfish-ejb-jar>
因此,生产者如何使用资源(JNDI)与消费者如何使用(XML + @ActivationConfigProperty)之间似乎存在一些不一致之处。此外,EE7 ActivationConfigProperty属性似乎不起作用。例如,使用 destinationLookup 不会查找目标,因此我不得不使用ActiveMQ的destination属性。
@ActivationConfigProperty
destination
ActiveMQ 列出了以下激活规范属性:
acknowledgeMode (JMS的确认模式来使用有效值包括:自动应答或复本-OK-确认) clientId (要使用的JMS客户端ID(仅持久主题才真正需要)) destinationType ( 目的地 的类型;队列或主题) 目标 (目标名称(队列或主题名称)) enableBatch (用于启用事务批处理以提高性能) maxMessagesPerBatch (每个事务批处理的消息数) maxMessagesPerSessions (这实际上是预订的预取大小。(是,名称不正确)。) maxSessions (要使用的最大并发会话数) messageSelector (要在订阅上使用的JMS消息选择器,以执行基于内容的路由来过滤消息) noLocal (仅对于主题订阅是必需的;指示是否应在订阅中包括本地发布的消息) 密码 (JMS连接的密码) subscriptionDurability (是否需要持久(主题)订阅。有效值为:Durable或NonDurable) subscriptionName (持久性订阅者的名称。仅用于持久性主题,并与clientID结合使用以唯一地标识持久性主题订阅) userName (JMS连接的用户) useRAManagedTransaction (通常,资源适配器将消息传递到由容器管理的端点。通常,此容器喜欢成为想要控制入站消息传递的事务的容器。但是有时,您想传递这种情况下,如果将useRAManagedTransaction设置为true,则如果没有从MessageListener生成异常,则资源适配器将提交事务;如果引发异常,则回滚。) initialRedeliveryDelay (重新交付开始之前的延迟。也可以在ResourceAdapter上配置) maximumRedeliveries (最大重新交付次数或-1(无最大值)。也可以在ResourceAdapter上配置) redeliveryBackOffMultiplier (如果启用了指数 补偿 ,则使用该乘数。也可以在ResourceAdapter上配置) redeliveryUseExponentialBackOff (要启用指数补偿。也可以在ResourceAdapter上配置useJndi如果为true,则为false,将destination用作jndi名称)
acknowledgeMode (JMS的确认模式来使用有效值包括:自动应答或复本-OK-确认)
clientId (要使用的JMS客户端ID(仅持久主题才真正需要))
destinationType ( 目的地 的类型;队列或主题)
目标 (目标名称(队列或主题名称))
enableBatch (用于启用事务批处理以提高性能)
maxMessagesPerBatch (每个事务批处理的消息数)
maxMessagesPerSessions (这实际上是预订的预取大小。(是,名称不正确)。)
maxSessions (要使用的最大并发会话数)
messageSelector (要在订阅上使用的JMS消息选择器,以执行基于内容的路由来过滤消息)
noLocal (仅对于主题订阅是必需的;指示是否应在订阅中包括本地发布的消息)
密码 (JMS连接的密码)
subscriptionDurability (是否需要持久(主题)订阅。有效值为:Durable或NonDurable)
subscriptionName (持久性订阅者的名称。仅用于持久性主题,并与clientID结合使用以唯一地标识持久性主题订阅)
userName (JMS连接的用户)
useRAManagedTransaction (通常,资源适配器将消息传递到由容器管理的端点。通常,此容器喜欢成为想要控制入站消息传递的事务的容器。但是有时,您想传递这种情况下,如果将useRAManagedTransaction设置为true,则如果没有从MessageListener生成异常,则资源适配器将提交事务;如果引发异常,则回滚。)
initialRedeliveryDelay (重新交付开始之前的延迟。也可以在ResourceAdapter上配置)
maximumRedeliveries (最大重新交付次数或-1(无最大值)。也可以在ResourceAdapter上配置)
redeliveryBackOffMultiplier (如果启用了指数 补偿 ,则使用该乘数。也可以在ResourceAdapter上配置)
redeliveryUseExponentialBackOff (要启用指数补偿。也可以在ResourceAdapter上配置useJndi如果为true,则为false,将destination用作jndi名称)
Java EE7规范列出了以下激活规范属性:
acknowledgeMode (该属性用于指定当使用bean管理事务划分的邮件传递JMS确认模式,其值是AUTO_ACKNOWLEDGE或DUPS_OK_ACKNOWLEDGE。如果未指定该属性,JMS AUTO_ACKNOWLEDGE语义被假定。 messageSelector (此属性用于指定在确定JMS消息驱动的bean将接收哪些消息时使用的JMS消息选择器) destinationType (此属性用于指定消息驱动的Bean是否打算与队列或主题一起使用。该值必须为javax.jms.Queue或javax.jms.Topic。) destinationLookup (此属性用于指定JMS消息驱动Bean从其接收消息的JMS队列或主题。) connectionFactoryLookup (此属性用于指定JMS连接工厂,该工厂将用于连接到JMS提供程序,JMS消息驱动的Bean将从该JMS提供程序接收消息。) subscriptionDurability (如果打算将消息驱动的Bean与某个主题一起使用,则可以使用此属性来指示应使用持久预订还是非持久预订。此属性的值必须为Durable或NonDurable。) subscriptionName (如果打算将消息驱动的bean与主题一起使用,并且bean提供程序指示应使用持久预订,则此属性用于指定持久预订的名称。) clientId (此属性用于指定连接到JMS消息驱动的Bean将从其接收消息的JMS提供程序时将使用的JMS客户机标识符。如果未指定此属性,则将不设置客户机标识符。 )
acknowledgeMode (该属性用于指定当使用bean管理事务划分的邮件传递JMS确认模式,其值是AUTO_ACKNOWLEDGE或DUPS_OK_ACKNOWLEDGE。如果未指定该属性,JMS AUTO_ACKNOWLEDGE语义被假定。
messageSelector (此属性用于指定在确定JMS消息驱动的bean将接收哪些消息时使用的JMS消息选择器)
destinationType (此属性用于指定消息驱动的Bean是否打算与队列或主题一起使用。该值必须为javax.jms.Queue或javax.jms.Topic。)
destinationLookup (此属性用于指定JMS消息驱动Bean从其接收消息的JMS队列或主题。)
connectionFactoryLookup (此属性用于指定JMS连接工厂,该工厂将用于连接到JMS提供程序,JMS消息驱动的Bean将从该JMS提供程序接收消息。)
subscriptionDurability (如果打算将消息驱动的Bean与某个主题一起使用,则可以使用此属性来指示应使用持久预订还是非持久预订。此属性的值必须为Durable或NonDurable。)
subscriptionName (如果打算将消息驱动的bean与主题一起使用,并且bean提供程序指示应使用持久预订,则此属性用于指定持久预订的名称。)
clientId (此属性用于指定连接到JMS消息驱动的Bean将从其接收消息的JMS提供程序时将使用的JMS客户机标识符。如果未指定此属性,则将不设置客户机标识符。 )
在仅使用@Inject点和jndi查找的生产者和消费者中使用ActiveMQ资源的正确方法是什么?我想避免使用glassfish-ejb- jar.xml并使用定义队列名称@ActivationConfigProperty。
看来所有服务器的处理方式都有些不同。