【发布时间】:2015-11-19 15:52:06
【问题描述】:
在如何使用 JMS 资源以及在 @MessageDriven 注释上使用正确的 @ActivationConfigProperty 设置 activationConfig 方面似乎存在一些不一致之处。
首先,这是我的资源配置(glassfish-resources.xml,但可转换为其他部署描述符)。这适用于 Glassfish (asadmin add-resources glassfish-resources.xml) 以及 ActiveMQ Resource Adapter:
<?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 时,混乱就开始了。以下使用 mappedName 会引发异常:
@MessageDriven(mappedName = "jms/queue/myApp")
public class MessageBean implements MessageListener
警告:RAR8000:类中不存在方法 setName: org.apache.activemq.command.ActiveMQQueue 警告:RAR7097:否 类中的属性名称存在 setter 方法 org.apache.activemq.command.ActiveMQQueue 信息:访问未访问 参考资料:访问未访问的参考资料警告:RAR8501: ra [ activemq-rar ] 的端点激活期间出现异常, activationSpecClass [ org.apache.activemq.ra.ActiveMQActivationSpec ] :javax.resource.ResourceException:未知目标类型:空 严重: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:
警告: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 属性。
ActiveMQlists the following Activation Spec Properties:
acknowledgeMode(要使用的 JMS 确认模式。有效值 是:自动确认或 Dups-ok-acknowledge)
clientId(要使用的 JMS 客户端 ID(只有持久化时才真正需要) 主题))
destinationType(目的地类型;队列或主题)
destination(目标名称(队列或主题名称))
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 no false 当为 true 时,使用 目的地作为 jndi 名称)
Java EE7 规范lists the following Activation Spec Properties:
acknowledgeMode(此属性用于指定 JMS bean 管理时消息传递的确认模式 使用事务分界。其值为 Auto_acknowledge 或 Dups_ok_acknowledge。如果未指定此属性,则 JMS 假定为 AUTO_ACKNOWLEDGE 语义。
messageSelector(该属性用于指定JMS消息 用于确定 JMS 消息驱动的消息的选择器 bean是接收)
destinationType(该属性用于指定是否发送消息 驱动 bean 旨在与队列或主题一起使用。价值 必须是 javax.jms.Queue 或 javax.jms.Topic。)
destinationLookup(此属性用于指定 JMS 队列或 JMS 消息驱动 bean 将从中接收消息的主题。)
connectionFactoryLookup(该属性用于指定JMS 将用于连接到 JMS 提供程序的连接工厂 JMS 消息驱动 bean 将从中接收消息。)
subscriptionDurability(如果消息驱动 bean 旨在 与主题一起使用,此属性可用于指示是否 应使用持久或非持久订阅。这个的价值 属性必须是 Durable 或 NonDurable)
subscriptionName(此属性用于指定订阅者的名称 如果打算使用消息驱动 bean,则持久订阅 有一个主题,并且 bean 提供者已经表明一个持久的 应该使用订阅。)
clientId(此属性用于指定 JMS 客户端标识符 将在连接到 JMS 提供程序时使用 消息驱动bean就是接收消息。如果这个属性不是 指定,则客户端标识符将保持未设置。)
只有 @Inject 点和 jndi 查找在生产者和消费者中使用 ActiveMQ 资源的正确方法是什么?我想避免使用 glassfish-ejb-jar.xml 并使用 @ActivationConfigProperty 定义队列名称。
【问题讨论】:
标签: java glassfish jms activemq ejb-3.1