使用 JMS Tibco EMS JNDI 资源启动 Tomcat 时来自 Catalina 的 NullPointerException
NullPointerException from Catalina when starting Tomcat with JMS Tibco EMS JNDI resources
在我的 Primefaces 应用程序中,我想使用 atmosphere framework 的 JMSBroadcaster
以便在我的应用程序的 2 个实例之间传播消息。
为此,我需要查找 (JNDI) JMS ConnectionFactory
和 Topic
(我们使用的实现是 Tibco EMS)。
我是 JMS 的新手,我不知道如何在 Tomcat 的 context.xml
和 server.xml
中配置 Tibco JMS 资源(我没有使用活动的 MQ)。我试图在 Tomcat 8 中从 EMS 声明这些 JMS 资源。
我在 tomcat8/lib/
中添加了 tibjms-7.0.1.jar
和 jboss-jms-api_1.1_spec-1.0.1.Final.jar
但是,在 tomcat 启动时,我收到以下错误(即使没有部署任何 war):
SEVERE [main] org.apache.catalina.mbeans.GlobalResourcesLifecycleListener.createMBeans RuntimeException java.lang.NullPointerException
我无法弄清楚问题出在哪里(我不确定我是否可以获得有关此记录错误的更多详细信息)。
这是我的 tomcat 配置:
在server.xml
<Resource
id="atmosphereFactory"
name="jms/atmosphereFactory"
jndiName="atmosphereFactory"
auth="Container"
type="com.tibco.tibjms.naming.TibjmsInitialContextFactory"
factory="com.tibco.tibjms.naming.TibjmsObjectFactory"
factoryClass="com.tibco.tibjms.naming.TibjmsInitialContextFactory"
brokerName="localhost"
brokerURL="tcp://localhost:7222"
serverUrl="localhost:7222"
userName="admin"
password="" />
<Resource
id="atmosphere"
name="jms/atmosphere/test.atmo"
jndiName="atmosphere"
auth="Container"
type="com.tibco.tibjms.TibjmsTopic"
factory="com.tibco.tibjms.naming.TibjmsObjectFactory"
physicalName="test.atmo"/>
在context.xml
<ResourceLink
global="jms/atmosphereFactory"
name="jms/atmosphereFactory"
type="com.tibco.tibjms.naming.TibjmsInitialContextFactory" />
<ResourceLink
global="jms/atmosphere"
name="jms/atmosphere"
type="com.tibco.tibjms.TibjmsTopic" />
或者,我可能也对使用从 Spring.
注入的 ConnectionFactory
和 Topic
配置气氛 JMSBroadcaster
的方法感兴趣
我实际上使用了 Spring 来实例化 Jms 主题...
<!-- Connection to Tibco EMS -->
<bean id="tibjmsConnectionFactory" class="com.tibco.tibjms.TibjmsConnectionFactory">
<property name="serverUrl" value="${instance.jms.server}" />
<property name="userName" value="${instance.jms.login}"/>
<property name="userPassword" value="${instance.jms.password}"/>
</bean>
<bean id="jmsTemplateEms" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="tibjmsConnectionFactory" />
<property name="explicitQosEnabled" value="true" />
<property name="deliveryMode" value="2" />
<property name="sessionAcknowledgeModeName" value="CLIENT_ACKNOWLEDGE" />
<property name="sessionTransacted" value="false" />
<property name="receiveTimeout" value="${instance.wait.timeout}" />
</bean>
<bean id="pushJmsMessageListener" class="com.agipi.g2a.tiana.web.utils.PushJmsMessageListener" />
<bean id="atmosphereTopic" class="com.tibco.tibjms.TibjmsTopic">
<!-- nom du topic-->
<constructor-arg index="0" value="${instance.jms.atmosphere.topic.name}" />
</bean>
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="tibjmsConnectionFactory"/>
<property name="destination" ref="atmosphereTopic"/>
<property name="messageListener" ref="pushJmsMessageListener" />
</bean>
...并创建了一个 MessageListener,它监听气氛主题并将接收到的消息发布到 Push 事件总线 ...
class PushJmsMessageListener implements MessageListener {
private static final Logger LOGGER = LoggerFactory.getLogger(PushJmsMessageListener.class);
private static final String PROPERTY_PUSH_CHANNEL = "pushChannel";
@Override
public void onMessage(Message message) {
try {
EventBus eventBus = EventBusFactory.getDefault().eventBus();
TextMessage testMessage = (TextMessage) message;
LOGGER.info("Reception d'un message du topic atmosphere : {}", testMessage);
String canal = testMessage.getStringProperty(PROPERTY_PUSH_CHANNEL);
Object decodedObject = new JSONDecoder().decode(testMessage.getText());
LOGGER.info("Envoi du message sur le endpoint push [canal={},objet={}]", canal, decodedObject);
eventBus.publish(canal, decodedObject);
} catch (JMSException e) {
LOGGER.error("error.receiving.jms.message", e);
}
}
}
... 并创建了一个 Spring 服务来将我的消息发布到主题而不是推送 ...
@Service
@Scope(value = "singleton")
public class JmsAtmosphereServiceImpl implements JmsAtmosphereService {
@Autowired
@Qualifier("jmsTemplateEms")
private JmsTemplate jmsTemplate;
@Autowired
@Qualifier("atmosphereTopic")
private Topic atmosphereTopic;
@Override
public void sendMessage(String pushChannel, String jsonContent) {
jmsTemplate.send(atmosphereTopic, session -> {
TextMessage textMessage = session.createTextMessage(jsonContent);
textMessage.setStringProperty("pushChannel", pushChannel);
return textMessage;
});
}
}
...一些抽象的实用程序...
@Service
public class PushJmsUtils {
private static final String PUSH_DEFAULT_CHANNEL = "atmosphere";
@Autowired
private JmsAtmosphereService jmsAtmosphereService;
/**
* Propagate message JMS as JSON to JMS Atmosphere topic.
*
* @param channel push channel
* @param message object to send via push
*/
public void propagateMessage(String channel, Object message) {
String id = channel;
if (id.startsWith("/*")) {
id = PUSH_DEFAULT_CHANNEL;
}
jmsAtmosphereService.sendMessage(id, new JSONEncoder().encode(message));
}
}
.. 然后,我将我的消息发布到我的应用程序的多个实例,这些实例收听相同的气氛主题(包括发送消息的应用程序)。
pushJmsUtils.propagateMessage(canal,pushMessage);
在我的 Primefaces 应用程序中,我想使用 atmosphere framework 的 JMSBroadcaster
以便在我的应用程序的 2 个实例之间传播消息。
为此,我需要查找 (JNDI) JMS ConnectionFactory
和 Topic
(我们使用的实现是 Tibco EMS)。
我是 JMS 的新手,我不知道如何在 Tomcat 的 context.xml
和 server.xml
中配置 Tibco JMS 资源(我没有使用活动的 MQ)。我试图在 Tomcat 8 中从 EMS 声明这些 JMS 资源。
我在 tomcat8/lib/
tibjms-7.0.1.jar
和 jboss-jms-api_1.1_spec-1.0.1.Final.jar
但是,在 tomcat 启动时,我收到以下错误(即使没有部署任何 war):
SEVERE [main] org.apache.catalina.mbeans.GlobalResourcesLifecycleListener.createMBeans RuntimeException java.lang.NullPointerException
我无法弄清楚问题出在哪里(我不确定我是否可以获得有关此记录错误的更多详细信息)。
这是我的 tomcat 配置:
在server.xml
<Resource
id="atmosphereFactory"
name="jms/atmosphereFactory"
jndiName="atmosphereFactory"
auth="Container"
type="com.tibco.tibjms.naming.TibjmsInitialContextFactory"
factory="com.tibco.tibjms.naming.TibjmsObjectFactory"
factoryClass="com.tibco.tibjms.naming.TibjmsInitialContextFactory"
brokerName="localhost"
brokerURL="tcp://localhost:7222"
serverUrl="localhost:7222"
userName="admin"
password="" />
<Resource
id="atmosphere"
name="jms/atmosphere/test.atmo"
jndiName="atmosphere"
auth="Container"
type="com.tibco.tibjms.TibjmsTopic"
factory="com.tibco.tibjms.naming.TibjmsObjectFactory"
physicalName="test.atmo"/>
在context.xml
<ResourceLink
global="jms/atmosphereFactory"
name="jms/atmosphereFactory"
type="com.tibco.tibjms.naming.TibjmsInitialContextFactory" />
<ResourceLink
global="jms/atmosphere"
name="jms/atmosphere"
type="com.tibco.tibjms.TibjmsTopic" />
或者,我可能也对使用从 Spring.
注入的ConnectionFactory
和 Topic
配置气氛 JMSBroadcaster
的方法感兴趣
我实际上使用了 Spring 来实例化 Jms 主题...
<!-- Connection to Tibco EMS -->
<bean id="tibjmsConnectionFactory" class="com.tibco.tibjms.TibjmsConnectionFactory">
<property name="serverUrl" value="${instance.jms.server}" />
<property name="userName" value="${instance.jms.login}"/>
<property name="userPassword" value="${instance.jms.password}"/>
</bean>
<bean id="jmsTemplateEms" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="tibjmsConnectionFactory" />
<property name="explicitQosEnabled" value="true" />
<property name="deliveryMode" value="2" />
<property name="sessionAcknowledgeModeName" value="CLIENT_ACKNOWLEDGE" />
<property name="sessionTransacted" value="false" />
<property name="receiveTimeout" value="${instance.wait.timeout}" />
</bean>
<bean id="pushJmsMessageListener" class="com.agipi.g2a.tiana.web.utils.PushJmsMessageListener" />
<bean id="atmosphereTopic" class="com.tibco.tibjms.TibjmsTopic">
<!-- nom du topic-->
<constructor-arg index="0" value="${instance.jms.atmosphere.topic.name}" />
</bean>
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="tibjmsConnectionFactory"/>
<property name="destination" ref="atmosphereTopic"/>
<property name="messageListener" ref="pushJmsMessageListener" />
</bean>
...并创建了一个 MessageListener,它监听气氛主题并将接收到的消息发布到 Push 事件总线 ...
class PushJmsMessageListener implements MessageListener {
private static final Logger LOGGER = LoggerFactory.getLogger(PushJmsMessageListener.class);
private static final String PROPERTY_PUSH_CHANNEL = "pushChannel";
@Override
public void onMessage(Message message) {
try {
EventBus eventBus = EventBusFactory.getDefault().eventBus();
TextMessage testMessage = (TextMessage) message;
LOGGER.info("Reception d'un message du topic atmosphere : {}", testMessage);
String canal = testMessage.getStringProperty(PROPERTY_PUSH_CHANNEL);
Object decodedObject = new JSONDecoder().decode(testMessage.getText());
LOGGER.info("Envoi du message sur le endpoint push [canal={},objet={}]", canal, decodedObject);
eventBus.publish(canal, decodedObject);
} catch (JMSException e) {
LOGGER.error("error.receiving.jms.message", e);
}
}
}
... 并创建了一个 Spring 服务来将我的消息发布到主题而不是推送 ...
@Service
@Scope(value = "singleton")
public class JmsAtmosphereServiceImpl implements JmsAtmosphereService {
@Autowired
@Qualifier("jmsTemplateEms")
private JmsTemplate jmsTemplate;
@Autowired
@Qualifier("atmosphereTopic")
private Topic atmosphereTopic;
@Override
public void sendMessage(String pushChannel, String jsonContent) {
jmsTemplate.send(atmosphereTopic, session -> {
TextMessage textMessage = session.createTextMessage(jsonContent);
textMessage.setStringProperty("pushChannel", pushChannel);
return textMessage;
});
}
}
...一些抽象的实用程序...
@Service
public class PushJmsUtils {
private static final String PUSH_DEFAULT_CHANNEL = "atmosphere";
@Autowired
private JmsAtmosphereService jmsAtmosphereService;
/**
* Propagate message JMS as JSON to JMS Atmosphere topic.
*
* @param channel push channel
* @param message object to send via push
*/
public void propagateMessage(String channel, Object message) {
String id = channel;
if (id.startsWith("/*")) {
id = PUSH_DEFAULT_CHANNEL;
}
jmsAtmosphereService.sendMessage(id, new JSONEncoder().encode(message));
}
}
.. 然后,我将我的消息发布到我的应用程序的多个实例,这些实例收听相同的气氛主题(包括发送消息的应用程序)。
pushJmsUtils.propagateMessage(canal,pushMessage);