we migrated a websphere j2ee app to spring boot. Everything looked great but now we found out that the message listeners are sometimes processing some messages twice.
It looks like to me it happens when one message is been processed and not yet commited, an other concurrent consumer can get the same message and also process it.
Looks like the message broker doesn't hold it back, doesn't reserves it for consumer 1.
import bitronix.tm.resource.jms.PoolingConnectionFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.springframework.transaction.PlatformTransactionManager;
import javax.jms.ConnectionFactory;
import javax.jms.Session;
import java.util.Properties;
#Configuration
#EnableJms
#EnableCaching(proxyTargetClass = true)
public class JmsConfig {
#Bean
ConnectionFactory jmsXAConnectionFactory() {
PoolingConnectionFactory connectionFactory = new PoolingConnectionFactory();
connectionFactory.setClassName("com.ibm.mq.jms.MQXAQueueConnectionFactory");
connectionFactory.setUniqueName("mq-xa-" + appName);
connectionFactory.setAllowLocalTransactions(true);
connectionFactory.setTestConnections(false);
connectionFactory.setUser(user);
connectionFactory.setPassword(password);
connectionFactory.setMaxIdleTime(1800);
connectionFactory.setMinPoolSize(1);
connectionFactory.setMaxPoolSize(25);
connectionFactory.setAcquisitionTimeout(60);
connectionFactory.setAutomaticEnlistingEnabled(true);
connectionFactory.setDeferConnectionRelease(true);
connectionFactory.setShareTransactionConnections(false);
Properties driverProperties = connectionFactory.getDriverProperties();
driverProperties.setProperty("queueManager", queueManager);
driverProperties.setProperty("hostName", connName);
driverProperties.setProperty("port", "1414");
driverProperties.setProperty("channel", channel);
driverProperties.setProperty("transportType", "1");
driverProperties.setProperty("messageRetention", "1");
return connectionFactory;
}
#Primary
#Bean
public BitronixTransactionManager btronixTransactionManager() throws SystemException {
TransactionManagerServices.getConfiguration().setServerId("bitronix-tm-" + appName);
TransactionManagerServices.getConfiguration().setLogPart1Filename(jtaLogDir + "/btm1.tlog");
TransactionManagerServices.getConfiguration().setLogPart2Filename(jtaLogDir + "/btm2.tlog");
TransactionManagerServices.getTransactionManager().setTransactionTimeout(180);
return TransactionManagerServices.getTransactionManager();
}
#Bean
public PlatformTransactionManager platformTransactionManager(
BitronixTransactionManager transactionManager, UserTransaction userTransaction) {
return new JtaTransactionManager(userTransaction, transactionManager);
}
#Bean("wgstatusML")
public DefaultMessageListenerContainer wagenstatusMessageListenerContainer(
ConnectionFactory jmsXAConnectionFactory,
PlatformTransactionManager jtaTransactionManager,
#Qualifier("wagenstatusBean") WagenstatusBean wagenstatusBean) {
DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
container.setConnectionFactory(jmsXAConnectionFactory);
container.setTransactionManager(jtaTransactionManager);
container.setDestinationName(WAGENSTATUS_QUEUE);
container.setMessageListener(wagenstatusBean);
container.setAutoStartup(false);
container.setConcurrentConsumers(2);
container.setClientId("wgstatListener");
container.setSessionTransacted(false);
container.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE);
return container;
}
}
#Service("wagenstatusBean")
#Scope(SCOPE_PROTOTYPE)
public class WagenstatusBean extends AbstractMDB {
#Transactional(propagation = REQUIRED)
public void onMessage(javax.jms.Message msg) {
String localMessageText = null;
try {
try {
localMessageText = ((TextMessage) msg).getText();
} catch (JMSException e) {
}
// here goes the actual call to the impl
String errmsg = null;
readableMessageID = null;
try {
verarbeiteMeldung(msg);
} catch (InvalidMessageException ime) {
errmsg = ime.getMessage();
}
if (sendMessageToErrorQueue) {
// generate business logging entry
try {
logBusinessData(localMessageText, BusinessLogger.STATUS_ERROR);
} catch (Exception e) {
LOGGER.error("", e);
}
if (localMessageText != null) {
localMessageText = this.addErrorMessageToXML(localMessageText, errmsg);
}
DispatcherServiceLocator.getDispatcherBean().sendToDestination(
QueueNames.WAGENSTATUS_ERROR_QUEUE, localMessageText);
}
} catch (ConsistencyException ex) {
// ConsistencyException used internally in the EJBEnv
// framework/template needs to be catched and translated into an EJBException
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();;
// generate business logging entry
try {
// UE03772, RfC 169: BUSINESS LOGGING POINT
logBusinessData(localMessageText, BusinessLogger.STATUS_ERROR);
} catch (Exception e) {
LOGGER.error("", e);
}
LOGGER.error("Caught a ConsistencyException in WagenStatus-onMessage", ex);
} catch (RuntimeException ex) {
// this catching is done for logging purpouse only.
LOGGER.error("Caught a RuntimeException in WagenStatus-onMessage", ex);
// generate business logging entry
try {
logBusinessData(localMessageText, BusinessLogger.STATUS_ERROR);
} catch (Exception e) {
LOGGER.error("", e);
}
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();;
}
}
Related
I have 2 instances of my application on the same machine (although it could be on different machines as well) with two Tomcat instances with different ports and Apache ActiveMQ is embedded in the application.
I have configured a static network of brokers so that the message from one instance can be consumed by all other instance as well (each instance can be producer and consumer).
servlet:
package com.activemq.servlet;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import javax.jms.JMSException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.activemq.ActiveMQStartup;
import com.activemq.MQPublisher;
import com.activemq.SendMsg;
import com.activemq.SendMsgToAllInstance;
import com.activemq.TestPublisher;
/**
* Servlet implementation class ActiveMQStartUpServlet
*/
#WebServlet(value = "/activeMQStartUpServlet", loadOnStartup = 1)
public class ActiveMQStartUpServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private ActiveMQStartup mqStartup = null;
private static final Map pooledPublishers = new HashMap();
#Override
public void init(ServletConfig config) throws ServletException {
System.out.println("starting servelt--------------");
super.init(config);
//Apache Active MQ Startup
mqStartup = new ActiveMQStartup();
mqStartup.startBrokerService();
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(req.getParameter("distributedMsg"));
String mqConfig = null;
String distributedMsg = req.getParameter("distributedMsg");
String simpleMsg = req.getParameter("simpleMsg");
if (distributedMsg != null && !distributedMsg.equals(""))
mqConfig = "distributedMsg";
else if (simpleMsg != null && !simpleMsg.equals(""))
mqConfig = "simpleMsg";
MQPublisher publisher = acquirePublisher(mqConfig);
try {
publisher.publish(mqConfig);
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
releasePublisher(publisher);
}
}
#SuppressWarnings("unchecked")
private void releasePublisher(MQPublisher publisher) {
if (publisher == null) return;
#SuppressWarnings("rawtypes")
LinkedList publishers;
TestPublisher poolablePublisher = (TestPublisher)publisher;
publishers = getPooledPublishers(poolablePublisher.getConfigurationName());
synchronized (publishers) {
publishers.addLast(poolablePublisher);
}
}
private MQPublisher acquirePublisher(String mqConfig) {
LinkedList publishers = getPooledPublishers(mqConfig);
MQPublisher publisher = getMQPubliser(publishers);
if (publisher != null) return publisher;
try {
if (mqConfig.equals("distributedMsg"))
return new TestPublisher(MQConfiguration.getConfiguration("distributedMsg"), new SendMsgToAllInstance());
else
return new TestPublisher(MQConfiguration.getConfiguration("simpleMsg"), new SendMsg());
}catch(Exception e){
e.printStackTrace();
}
return null;
}
private LinkedList getPooledPublishers(String mqConfig) {
LinkedList publishers = null;
publishers = (LinkedList) pooledPublishers.get(mqConfig);
if (publishers == null) {
synchronized(pooledPublishers) {
publishers = (LinkedList) pooledPublishers.get(mqConfig);
if (publishers == null) {
publishers = new LinkedList();
pooledPublishers.put(mqConfig, publishers);
}
}
}
return publishers;
}
private MQPublisher getMQPubliser(LinkedList publishers) {
synchronized (publishers) {
while (!publishers.isEmpty()) {
TestPublisher publisher = (TestPublisher)publishers.removeFirst();
return publisher;
}
}
return null;
}
}
Configuration:
package com.activemq.servlet;
import java.util.HashMap;
import java.util.Map;
import javax.jms.JMSException;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicSession;
import org.apache.activemq.ActiveMQConnectionFactory;
import com.activemq.ActiveMQContext;
public class MQConfiguration {
private static final Map configurations = new HashMap();
private String mqConfig;
private String topicName;
private TopicConnection topicConnection = null;
private MQConfiguration(String mqConfig, String string, String string2) {
this.mqConfig = mqConfig;
try {
String topicFactoryConName = ActiveMQContext.getProperty(mqConfig);
this.topicName = (mqConfig.equals("distributedMsg") ? ActiveMQContext.getProperty("distributedTopic"):ActiveMQContext.getProperty("normalTopic"));
TopicConnectionFactory factory = (ActiveMQConnectionFactory) ActiveMQContext.getContext()
.lookup(topicFactoryConName);
this.topicConnection = factory.createTopicConnection();
this.topicConnection.start();
} catch (Exception e) {
System.out.println("error: " + e);
}
}
public static MQConfiguration getConfiguration(String mqConfig) {
if (mqConfig == null || "".equals(mqConfig)) {
throw new IllegalArgumentException("mqConfig is null or empty");
}
MQConfiguration config = null;
if (config != null) {
return config;
}
synchronized (configurations) {
config = (MQConfiguration) configurations.get(mqConfig);
if (config == null) {
config = new MQConfiguration(mqConfig, "userName", "userPassword");
}
configurations.put(mqConfig, config);
}
return config;
}
public String getMqConfig() {
return this.mqConfig;
}
public TopicSession createTopicSession(boolean isTransacted, int autoAcknowledge) throws JMSException {
if (this.topicConnection == null) {
IllegalStateException ise = new IllegalStateException("topic connection not configured");
throw ise;
}
return this.topicConnection.createTopicSession(isTransacted, autoAcknowledge);
}
public Topic getTopic() {
try {
return (Topic) ActiveMQContext.getContext().lookup(this.topicName);
} catch (Exception e) {
e.getMessage();
}
return null;
}
}
publisher:
package com.activemq;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import com.activemq.servlet.MQConfiguration;
public class TestPublisher implements MQPublisher {
private final String configurationName;
private TopicSession topicSession = null;
private TopicPublisher topicPublisher = null;
public TestPublisher(MQConfiguration config, Object messageListener) throws JMSException {
if (config == null) {
throw new IllegalArgumentException("config == null");
}
Topic topic = config.getTopic();
this.configurationName = config.getMqConfig();
this.topicSession = config.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
this.topicPublisher = this.topicSession.createPublisher(topic);
MessageConsumer msgConsumer = this.topicSession.createConsumer(topic);
msgConsumer.setMessageListener((MessageListener) messageListener);
}
#Override
public void publish(String msg) throws JMSException {
this.topicPublisher.publish(createMessage(msg, this.topicSession));
}
private Message createMessage(String msg, Session session) throws JMSException {
TextMessage message = session.createTextMessage(msg);
return message;
}
public String getConfigurationName() {
return this.configurationName;
}
}
Consumer:
package com.activemq;
import javax.jms.Message;
import javax.jms.MessageListener;
public class SendMsgToAllInstance implements MessageListener {
#Override
public void onMessage(Message arg0) {
System.out.println("distributed message-------------");
// We have call to dao layer to to fetch some data and cached it
}
}
JNDI:activemq-jndi.properties
# JNDI properties file to setup the JNDI server within ActiveMQ
#
# Default JNDI properties settings
#
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://localhost:61616
activemq.network.connector=static:(tcp://localhost:61620)
#activemq.network.connector=broker:(tcp://localhost:61619,network:static:tcp://localhost:61620)?persistent=false&useJmx=true
activemq.data.directory=data61619
activemq.jmx.port=1099
#
# Set the connection factory name(s) as well as the destination names. The connection factory name(s)
# as well as the second part (after the dot) of the left hand side of the destination definition
# must be used in the JNDI lookups.
#
connectionFactoryNames = distributedMsgFactory,simpleMsgFactory
topic.jms/distributedTopic=distributedTopic
topic.jms/normalTopic=normalTopic
distributedMsg=distributedMsgFactory
simpleMsg=simpleMsgFactory
distributedTopic=jms/distributedTopic
normalTopic=jms/normalTopic
ActiveMQStartup:
package com.activemq;
import java.net.URI;
import org.apache.activemq.broker.BrokerPlugin;
import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.broker.TransportConnector;
import org.apache.activemq.broker.jmx.ManagementContext;
import org.apache.activemq.network.NetworkConnector;
import org.apache.activemq.security.JaasAuthenticationPlugin;
public class ActiveMQStartup {
private final String bindAddress;
private final String dataDirectory;
private BrokerService broker = new BrokerService();
protected final int numRestarts = 3;
protected final int networkTTL = 2;
protected final int consumerTTL = 2;
protected final boolean dynamicOnly = true;
protected final String networkBroker;
protected final String jmxPort;
public ActiveMQStartup() {
ActiveMQContext context = new ActiveMQContext();
context.loadJndiProperties();
bindAddress = ActiveMQContext.getProperty("java.naming.provider.url");
dataDirectory = ActiveMQContext.getProperty("activemq.data.directory");
networkBroker = ActiveMQContext.getProperty("activemq.network.connector");
jmxPort = ActiveMQContext.getProperty("activemq.jmx.port");
}
// Start activemq broker service
public void startBrokerService() {
try {
broker.setDataDirectory("../" + dataDirectory);
broker.setBrokerName(dataDirectory);
broker.setUseShutdownHook(true);
TransportConnector connector = new TransportConnector();
connector.setUri(new URI(bindAddress));
//broker.setPlugins(new BrokerPlugin[]{new JaasAuthenticationPlugin()});
ManagementContext mgContext = new ManagementContext();
if (networkBroker != null && !networkBroker.isEmpty()) {
NetworkConnector networkConnector = broker.addNetworkConnector(networkBroker);
networkConnector.setName(dataDirectory);
mgContext.setConnectorPort(Integer.parseInt(jmxPort));
broker.setManagementContext(mgContext);
configureNetworkConnector(networkConnector);
}
broker.setNetworkConnectorStartAsync(true);
broker.addConnector(connector);
broker.start();
} catch (Exception e) {
System.out.println("Failed to start Apache MQ Broker : " + e);
}
}
private void configureNetworkConnector(NetworkConnector networkConnector) {
networkConnector.setDuplex(true);
networkConnector.setNetworkTTL(networkTTL);
networkConnector.setDynamicOnly(dynamicOnly);
networkConnector.setConsumerTTL(consumerTTL);
//networkConnector.setStaticBridge(true);
}
// Stop broker service
public void stopBrokerService() {
try {
broker.stop();
} catch (Exception e) {
System.out.println("Unable to stop the ApacheMQ Broker service " + e);
}
}
}
I am starting the tomcat instance one by one and seeing the network connection between the broker is getting established.
When I am sending messge from instance1 or instance2(first time) it is consuming on that instance only, but when I am sending message from the second instance it is consumed by both;
Code in git: https://github.com/AratRana/ApacheActiveMQ
Could you point me where I am wrong?
Finally, I am able to do it. When I started the consumer during server startup then I am able to see the message consumer in all instances. So to achieve this the consumers needs to be started before publishing any message.
I am newbie to MQ, We are usgin spring boot with JMS + IBM MQ Framework. We are facing a very random issue where there is 5 - 15 min delay to execute send method of jmsQueueTemplate as below.
Random delay is Between //POINT 1 and //POINT 2
try {
logger.info("Calling Send Method ");
//POINT 1
jmsQueueTemplate.send(new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
JMSTextMessage message = null;
try {
//POINT 2
logger.info("Session Object ........ " + session.toString());
logger.info("Session Status - Is Session Transacted ?........ " + session.getTransacted());
logger.info("Session Status acknowledge mode........ " + session.getAcknowledgeMode());
logger.info("Ready to send Sample message........ ");
logger.info("Send ConnectionFactory is: " + jmsQueueTemplate.getConnectionFactory().toString());
logger.info("Send destination is: " + jmsQueueTemplate.getDefaultDestination());
logger.info("Reply destination is: " + destination);
logger.info("Sent message correlationId is: " + correlationId);
logger.info("##########################################################");
message = (JMSTextMessage) session.createTextMessage();
String fosXmlBatchRequest = XMLUtil.createBatchFosRequestXML(oBatchFosRequest);
message.setText(fosXmlBatchRequest);
message.setJMSCorrelationID(correlationId);
logger.info(transactionType + " : Sending message is:");
logger.info(message.getText());
logger.info("##########################################################");
message.setJMSReplyTo(destination);
} catch (Exception e) {
logger.info("Exception Occured :" + e.getMessage());
}
return message;
}
});
} catch(Exception e) {
logger.info("Exception while Sending Message To FOS",e);
logger.info(e.toString(),e);
logger.error("Exception while Sending Message To FOS",e);
logger.error(e.toString(),e);
}
we are not handling session object and letting spring take care of session creation . I am not sure when exacty is the delay getting introced ? Are we loosing session object ? Any suggestion pls.
Our spring configuration is as below .
import javax.jms.Destination;
import javax.jms.JMSException;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.MessageType;
import org.springframework.stereotype.Component;
import com.ibm.mq.jms.MQQueue;
import com.ibm.mq.jms.MQQueueConnectionFactory;
/**
*
* #author krna
* This class defines configuration for JMS Queues required for FOS update.
*/
#Configurable
#Component
public class JMSConfiguration {
private final Logger log = LogManager.getLogger(JMSConfiguration.class);
#Autowired
MessageListenerReciever messageListenerReciever1;
#Autowired
MessageListenerReciever messageListenerReciever2;
private String hostName1;
private String hostName2;
private String hostName3;
private String writePort;
private String readPort;
private String channel;
private String transportType;
private String updateQueue;
private String replyQueue;
private String queueGateway;
#Autowired
JMSConfiguration(Environment environment){
this.hostName1 = environment.getRequiredProperty("jms.cf.write.hostName1");
this.hostName2 = environment.getRequiredProperty("jms.cf.read.hostName2");
this.hostName3 = environment.getRequiredProperty("jms.cf.read.hostName3");
this.writePort = environment.getRequiredProperty("jms.cf.write.port");
this.readPort = environment.getRequiredProperty("jms.cf.read.port");
this.channel = environment.getRequiredProperty("jms.cf.channel");
this.transportType = environment.getRequiredProperty("jms.cf.transportType");
this.updateQueue = environment.getRequiredProperty("jms.queue.update");
this.replyQueue = environment.getRequiredProperty("jms.queue.reply");
this.queueGateway = environment.getRequiredProperty("jms.queue.gateway");
}
public MQQueueConnectionFactory connectionFactory1() {
MQQueueConnectionFactory connectionFactory = new MQQueueConnectionFactory();
try {
connectionFactory.setHostName(hostName1);
connectionFactory.setPort(Integer.parseInt(writePort));
connectionFactory.setChannel(channel);
connectionFactory.setTransportType(Integer.parseInt(transportType));
} catch (NumberFormatException | JMSException e) {
log.error(e.toString(),e);
}
return connectionFactory;
}
public MQQueueConnectionFactory connectionFactory2() {
MQQueueConnectionFactory connectionFactory = new MQQueueConnectionFactory();
try {
connectionFactory.setHostName(hostName2);
connectionFactory.setPort(Integer.parseInt(readPort));
connectionFactory.setChannel(channel);
connectionFactory.setTransportType(Integer.parseInt(transportType));
} catch (NumberFormatException | JMSException e) {
log.error(e.toString(),e);
}
return connectionFactory;
}
public MQQueueConnectionFactory connectionFactory3() {
MQQueueConnectionFactory connectionFactory = new MQQueueConnectionFactory();
try {
connectionFactory.setHostName(hostName3);
connectionFactory.setPort(Integer.parseInt(readPort));
connectionFactory.setChannel(channel);
connectionFactory.setTransportType(Integer.parseInt(transportType));
} catch (NumberFormatException | JMSException e) {
log.error(e.toString(),e);
}
return connectionFactory;
}
#Bean
public Destination jmsDestinationResolverSender() throws JMSException {
return new MQQueue(updateQueue);
}
#Bean
public Destination jmsDestinationResolverReceiver() throws JMSException {
return new MQQueue(replyQueue);
}
#Bean
public Destination jmsDestinationResolverReplyTo() throws JMSException {
return new MQQueue(queueGateway, replyQueue);
}
#Bean
public JmsTemplate jmsQueueTemplate() throws JMSException {
JmsTemplate jmsTemplate = new JmsTemplate();
jmsTemplate.setConnectionFactory(connectionFactory1());
jmsTemplate.setDefaultDestination(jmsDestinationResolverSender());
jmsTemplate.afterPropertiesSet();
log.info("Send ConnectionFactory is:" + jmsTemplate.getConnectionFactory());
log.info("Send destination is:" + jmsTemplate.getDefaultDestination());
log.info("Send Delivery Delay is :" + jmsTemplate.getDeliveryDelay());
log.info("Send Delivery Mode is:" + jmsTemplate.getDeliveryMode());
return jmsTemplate;
}
#Bean
public DefaultMessageListenerContainer listenerContainer() throws JMSException {
DefaultMessageListenerContainer defMsgListCont = new DefaultMessageListenerContainer();
defMsgListCont.setConnectionFactory(connectionFactory3());
defMsgListCont.setDestination(jmsDestinationResolverReceiver());
defMsgListCont.setMessageListener(messageListenerReciever1);
defMsgListCont.afterPropertiesSet();
return defMsgListCont;
}
#Bean
public DefaultMessageListenerContainer listenerContainer2() throws JMSException {
DefaultMessageListenerContainer defMsgListCont = new DefaultMessageListenerContainer();
defMsgListCont.setConnectionFactory(connectionFactory2());
defMsgListCont.setDestination(jmsDestinationResolverReceiver());
defMsgListCont.setMessageListener(messageListenerReciever2);
defMsgListCont.afterPropertiesSet();
return defMsgListCont;
}
// Serialize message content to json using TextMessage
#Bean
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("_type");
return converter;
}
}
Update: It happened again today. One more Interesting this is sourcetimestamp on MQ msg is different from the time it was send. Sourcetimestamp is showing correct time but execution is delayed
I am facing below error when I run my java application which uses spring framework and ehcache for cache implementation. This application is build on IBM Integration Bus which Java and spring framework.
The full error stack is as below
+BIP2230E (Msg 2/4) MQJLMBRK ARCI511 147 ERROR DETECTED WHILST PROCESSI
NG A MESSAGE IN NODE 'ARFAL_MobilePortProtection01.FailureHandler.Tran
sform Failure'.
+BIP4367E (Msg 3/4) MQJLMBRK ARCI511 147 THE METHOD 'evaluate' IN JAVA
NODE 'FailureHandler.Transform Failure' HAS THROWN THE FOLLOWING EXCEP
TION: java.lang.NoSuchMethodError: org/ehcache/jcache/JCacheManager.ge
tEhCacheNativeCacheManager()Lnet/sf/ehcache/CacheManager;.
+BIP4395E (Msg 4/4) MQJLMBRK ARCI511 147 JAVA EXCEPTION: 'java.lang.NoS
uchMethodError'; THROWN FROM CLASS NAME: 'com.anz.common.cache.impl.Lo
calCacheHandler', METHOD NAME: 'getCacheManager', FILE: 'LocalCacheHan
dler.java', LINE: '99'
The code where error has triggered is as below
/**
*
*/
package com.anz.common.cache.impl;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.net.MalformedURLException;
import java.net.URL;
import javax.cache.Cache;
import javax.cache.configuration.MutableConfiguration;
import javax.management.MBeanServer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.ehcache.jcache.JCacheManager;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.management.ManagementService;
/**
* ehCache Cache Handler in JCashe JSR107 standard API
* Cache Handler Factory -> Cache Handler -> Caching Provider -> Cache Manager -> Cache
* #author sanketsw
*
*/
public class LocalCacheHandler extends AbstractCacheHandler {
private static final Logger logger = LogManager.getLogger();
public static LocalCacheHandler _inst = null;
public LocalCacheHandler() throws Exception {
super();
}
/*public static LocalCacheHandler getInstance() throws Exception {
if (_inst == null) {
_inst = new LocalCacheHandler();
}
return _inst;
}*/
#Override
public String getDefaultCacheName() {
return "DefaultMap";
}
#Override
public String getCachingProviderName() {
return "org.ehcache.jcache.JCacheCachingProvider";
}
/* (non-Javadoc)
* #see com.anz.common.cache.impl.AbstractCacheHandler#getCache(java.lang.String)
*/
#Override
public Cache<String, String> getCache(String cacheName) throws CacheException, Exception {
Cache<String, String> cache = null;
try {
//logger.debug("Retriving cache {}", cacheName);
cache = cacheManager.getCache(cacheName);
} catch(Exception e) {
//logger.debug("Retriving cache using type classes {}", cacheName);
try {
cache = cacheManager.getCache(cacheName, String.class, String.class);
}catch(Exception e2) {
logger.throwing(e2);
}
}
if (cache == null) {
//logger.debug("Starting cache {}", cacheName);
MutableConfiguration<String, String> jcacheConfig = new MutableConfiguration<String, String>();
jcacheConfig.setTypes(String.class, String.class);
cache = cacheManager.createCache(cacheName, jcacheConfig);
}
return cache;
}
/* (non-Javadoc)
* #see com.anz.common.cache.impl.AbstractCacheHandler#getCacheManager()
*/
#Override
public javax.cache.CacheManager getCacheManager() throws Exception {
javax.cache.CacheManager ret = super.getCacheManager();
try {
// Register for JMX management
JCacheManager ehCacheManager = (JCacheManager)ret;
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
ehCacheManager.getEhCacheNativeCacheManager().setName("LocalCacheManager");
//logger.info("printing mBeanServer {}", mBeanServer);
//logger.info("printing EhCacheNativeCacheManager {}", ehCacheManager.getEhCacheNativeCacheManager());
ManagementService.registerMBeans(ehCacheManager.getEhCacheNativeCacheManager(), mBeanServer, true, true, true, true);
}catch(Exception e) {
//logger.info("net.sf.ehcache:type=CacheManager,name=LocalCacheManager is already registered for JMX management. Ignoring...");
//logger.info(e.getMessage());
}
return ret;
}
#Override
public String getCacheManagerURI() {
String path = System.getenv("CACHE_CONFIG");
//logger.info("System property CACHE_CONFIG={}",path);
File configFile = new File(path + "/" + "ehcache-localcache.xml");
if(configFile.exists()) {
try {
return configFile.toURI().toURL().toString();
} catch (MalformedURLException e) {
logger.throwing(e);
}
} else {
URL resource = LocalCacheHandler.class.getResource("ehcache-localcache.xml");
if(resource != null) {
//logger.warn("Loading a backup config file={}",resource);
return resource.toString();
}
}
//logger.warn("Could not load the resource {}", "ehcache-localcache.xml");
return null;
}
}
Any clue what could be the issue.
How can I create a Spring Aspect (annotation driven e.g. #ExceptionTranslation) surrounding an entire method and put this method in a try...catch method?
#ExceptionTranslation
public void method() {
// do some stuff here...
}
so logically it does:
public void method() {
try {
// do some stuff here ...
} catch( Exception ex ) {
}
}
Below you can find a sample implementation of AfterThrows advice solving your problem.
CustomException.java
package com.yourpackage;
public class CustomException extends Exception {
public CustomException(final Throwable cause) {
super(cause);
}
}
ErrorBean.java
package com.yourpackage;
public class ErrorBean {
#ExceptionTranslation
public void translatedException() throws Exception {
throw new Exception("Foo");
}
public void notTranslatedException() throws Exception {
throw new Exception("Bar");
}
}
ExceptionTranslation.java
package com.yourpackage;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface ExceptionTranslation {
}
SimpleThrowsAdvice.java
package com.yourpackage;
import org.springframework.aop.Advisor;
import org.springframework.aop.ThrowsAdvice;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
public class SimpleThrowsAdvice implements ThrowsAdvice {
public static void main(String[] args) throws Exception {
ErrorBean errorBean = new ErrorBean();
AnnotationMatchingPointcut pc = AnnotationMatchingPointcut.forMethodAnnotation(ExceptionTranslation.class);
SimpleThrowsAdvice advice = new SimpleThrowsAdvice();
Advisor advisor = new DefaultPointcutAdvisor(pc, advice);
ProxyFactory pf = new ProxyFactory();
pf.setTarget(errorBean);
pf.addAdvisor(advisor);
ErrorBean proxy = (ErrorBean) pf.getProxy();
try {
proxy.translatedException();
} catch (CustomException ex) {
System.out.println("CustomException caught");
} catch (Exception ex) {
System.out.println("Exception caught");
}
try {
proxy.notTranslatedException();
} catch (CustomException ex) {
System.out.println("CustomException caught");
} catch (Exception ex) {
System.out.println("Exception caught");
}
}
public void afterThrowing(Exception ex) throws Throwable {
System.out.println("***");
System.out.println("Generic Exception Capture");
System.out.println("Caught: " + ex.getClass().getName());
System.out.println("***\n");
throw new CustomException(ex);
}
}
I have activemq5.3.2 running and I wanted to subscribe existing advisory topics using my java program. while, `jndi` lookup I am getting following error:
javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:
java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:657)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:259)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:296)
at javax.naming.InitialContext.lookup(InitialContext.java:363)
at jmsclient.Consumer.<init>(Consumer.java:38)
at jmsclient.Consumer.main(Consumer.java:74)
Exception occurred: javax.jms.InvalidDestinationException: Don't understand null destinations
Please suggest where the problem is, or how could I use my topic name to look for?
package jmsclient;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Consumer implements MessageListener {
private static int ackMode;
private static String clientTopicName;
private boolean transacted = false;
//private MessageConsumer messageConsumer;
static {
clientTopicName = "ActiveMQ.Advisory.Consumer.Queue.example.A";
ackMode = Session.AUTO_ACKNOWLEDGE;
}
#SuppressWarnings("null")
public Consumer()
{// TODO Auto-generated method stub
TextMessage message = null;
Context jndiContext;
//TopicConnectionFactory topicConnectionFactory = null;
TopicConnection topicConnection = null;
TopicSession topicSession = null;
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://usaxwas012ccxra.ccmp.ibm.lab:61616");
try{
Topic myTopic = null;
try { jndiContext = new InitialContext();
myTopic = (Topic) jndiContext.lookup(clientTopicName);
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
topicConnection = connectionFactory.createTopicConnection();
topicConnection.start();
topicSession = topicConnection.createTopicSession(transacted, ackMode);
TopicSubscriber topicSubscriber = topicSession.createSubscriber(myTopic);
Message m = topicSubscriber.receive(1000);
if (m != null) {
if (m instanceof TextMessage) {
message = (TextMessage) m;
System.out.println("Reading message: " + message.getText());
}
}
} //try ends
catch (JMSException e) {
System.out.println("Exception occurred: " + e.toString());
} finally {
if (topicConnection != null) {
try {
topicConnection.close();
} catch (JMSException e) {}
}}}
public void onMessage(Message arg0) {
// TODO Auto-generated method stub
}
public static void main(String[] args) {
new Consumer();
}
}