ActiveMQ message redelivery delay not working - java

I have configured an ActiveMQ message queue with transactions in a Spring Boot application.
Here is my beans configuration:
#Bean
public DefaultJmsListenerContainerFactory jmsListenerFactory(DefaultJmsListenerContainerFactoryConfigurer configurer,
#Qualifier("jmsTransactionManager") PlatformTransactionManager transactionManager,
JmsErrorHandler errorHandler) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
configurer.configure(factory, connectionFactory());
factory.setMessageConverter(messageConverter());
factory.setTransactionManager(transactionManager);
factory.setSessionTransacted(true);
factory.setErrorHandler(errorHandler);
return factory;
}
#Bean
public RedeliveryPolicy redeliveryPolicy() {
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
redeliveryPolicy.setInitialRedeliveryDelay(20000);
redeliveryPolicy.setRedeliveryDelay(20000);
redeliveryPolicy.setMaximumRedeliveryDelay(20000);
redeliveryPolicy.setBackOffMultiplier(2);
redeliveryPolicy.setUseExponentialBackOff(true);
redeliveryPolicy.setMaximumRedeliveries(-1);
redeliveryPolicy.setDestination(defaultDestination());
return redeliveryPolicy;
}
#Bean
public ActiveMQConnectionFactory connectionFactory() {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(getAddress());
connectionFactory.setRedeliveryPolicy(redeliveryPolicy());
return connectionFactory;
}
#Bean(initMethod = "start", destroyMethod = "stop")
public BrokerService broker() throws Exception {
final BrokerService broker = new BrokerService();
broker.addConnector(getAddress());
PersistenceAdapter persistenceAdapter = new KahaDBPersistenceAdapter();
persistenceAdapter.setDirectory(new File(...));
broker.setPersistenceAdapter(persistenceAdapter);
broker.setBrokerName(getName());
broker.setPersistent(true);
broker.setDataDirectoryFile(new File(...));
broker.setSchedulerSupport(true);
broker.setUseJmx(true);
return broker;
}
#Bean
public JmsTemplate jmsTemplate() {
JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory());
jmsTemplate.setMessageConverter(messageConverter());
jmsTemplate.setSessionTransacted(true);
jmsTemplate.setSessionAcknowledgeMode(Session.SESSION_TRANSACTED);
jmsTemplate.setDefaultDestination(defaultDestination());
jmsTemplate.setPubSubDomain(false);
return jmsTemplate;
}
Although maximum redeliveries attribute is working as expected (unlimited) the delay setting is not, which is strange.
Any tips on what might be the issue?
EDIT
I found that the issue disappears when I comment out this:
factory.setTransactionManager(transactionManager);
from jmsListenerFactory. I am not sure if I understand the reason though and if it is safe to completely remove it.

Related

How to configure multiple JmsListenerContainerFactories from multiple JNDI names of JMS in Springboot application?

I should be able to configure multiple JmsListenerContainerFactory beans from multiple JMS JNDI names configured in the server and I should be able to do the following.
#EnableJms
#Configuration
public class JmsConfig
{
#Bean
public JmsListenerContainerFactory<?> containerFactoryONE(#Qualifier("from-JNDI-ONE") ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer)
{
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
configurer.configure(factory, connectionFactory);
return factory;
}
#Bean
public JmsListenerContainerFactory<?> containerFactoryTWO(#Qualifier("from-JNDI-TWO") ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer)
{
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
configurer.configure(factory, connectionFactory);
return factory;
}
}
and should be able to listen to the message from two different servers as below
#Component
public class JMSListener
{
#JmsListener(destination = "jms/ActiveMQ-Server-ONE", containerFactory="containerFactoryONE")
public void receiveMessageFromJMSServerONE(String message)
{
System.out.println(message);
}
#JmsListener(destination = "jms/ActiveMQ-Server-TWO", containerFactory="containerFactoryTWO")
public void receiveMessageFromJMSServerTWO(String message)
{
System.out.println(message);
}
}

Why error javax.jms.InvalidDestinationException: Not allowed to create destination? Problem with send message to MQ with spring boot app

Hey guys I have an application with spring boot that receives a message from a TIBCO EMS, I perform some operations and finally, I need to send that message to an MQ
I have a class Consumer
In the line #JmsLister I have a destination queue from TIBCO EMS because is who sends the message and when I called a method sendMessage I pass a destination queue from the parameter that is to MQ
#Component
public class ClassConsumer {
#JmsListener(destination = "${jms.destination.queue}",
containerFactory = Constants.GENERIC_JMS_EMS_LISTENER_BEAN_NAME)
public void consumerProcess(String request, #Header(JmsHeaders.ID) String id) {
ValoresDtoIn in = operationService.convertXml(request);
DatosDto datosDto = operationService.fillObject(in);
this.operacionService.sendMessage(datosDto, mqConstants.getMqDestiQueue(),id);
}
}
and when it reaches the sendMessage method it marks the error
This is my class service
#Service
public class Operations implements OperationsService {
#Autowired
#Qualifier(Constants.GENERIC_JMS_TEMPLATE_BEAN_NAME)
private JmsTemplate jmsTemplate;
#Override
public void sendMessage(String message, String destination, String id) {
ConnectionFactory connectionFactory = this.jmsTemplate.getConnectionFactory();
if (!Objects.isNull(connectionFactory)) {
try (Connection connection = connectionFactory.createConnection()) {
Queue queue = connection.createSession().createQueue(destination);
this.processorService.setId(id);
this.jmsTemplate.convertAndSend(queue, message, this.processorService);
} catch (JMSException ex) {
LOGGER.error(ex.getMessage(), ex);
}
}
}
}
and I had two classes from configuration, one for TibEms and the other from MQ
to TIBCO
#Configuration
public class TibConnectionConfig {
#Bean(name = Constants.GENERIC_CONNECTION_FACTORY_BEAN_NAME)
public TibjmsConnectionFactory tibjmsConnectionFactory() throws JMSException {
TibjmsConnectionFactory tibjmsConnectionFactory = new TibjmsConnectionFactory();
tibjmsConnectionFactory.setServerUrl(constants.getGenericHost());
tibjmsConnectionFactory.setUserName(constants.getGenericUsername());
tibjmsConnectionFactory.setUserPassword(constants.getGenericPassword());
tibjmsConnectionFactory.setReconnAttemptTimeout(constants.getGenericReconnAttemptTimeout());
tibjmsConnectionFactory.setSSLPassword(constants.getCertificatePassword());
tibjmsConnectionFactory.setSSLTrustedCertificate(constants.getCertificatePath());
tibjmsConnectionFactory.setSSLEnableVerifyHostName(false);
return tibjmsConnectionFactory;
}
#Bean(name = Constants.GENERIC_CACHING_CONNECTION_FACTORY_BEAN_NAME)
public CachingConnectionFactory cachingConnectionFactory(
#Qualifier(Constants.GENERIC_CONNECTION_FACTORY_BEAN_NAME) TibjmsConnectionFactory tibjmsConnectionFactory)
throws JMSException {
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(tibjmsConnectionFactory());
cachingConnectionFactory.setSessionCacheSize(constants.getGenericCacheSize());
return cachingConnectionFactory;
}
#Bean(name = Constants.GENERIC_JMS_TEMPLATE_BEAN_NAME)
public JmsTemplate jmsTemplate(
#Qualifier(Constants.GENERIC_CACHING_CONNECTION_FACTORY_BEAN_NAME) CachingConnectionFactory connection)
throws JMSException {
JmsTemplate jmsTemplate = new JmsTemplate(connection);
jmsTemplate.setDefaultDestinationName(constants.getGenericDestinationQueue());
jmsTemplate.setReceiveTimeout(constants.getGenericReceiveTimeout());
jmsTemplate.setDeliveryMode(constants.getGenericDeliverymode());
jmsTemplate.setSessionAcknowledgeModeName(constants.getSessionMode());
jmsTemplate.setExplicitQosEnabled(true);
jmsTemplate.setSessionTransacted(false);
return jmsTemplate;
}
#Bean(name = Constants.GENERIC_JMS_EMS_LISTENER_BEAN_NAME)
public DefaultJmsListenerContainerFactory jmsEmsListenerContainerFactory(
#Qualifier(Constants.GENERIC_CACHING_CONNECTION_FACTORY_BEAN_NAME) CachingConnectionFactory connection,
GenericErrorHandler genericErrorHandler) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connection);
factory.setErrorHandler(genericErrorHandler);
factory.setConcurrency(Constants.CONCURRENT_CONSTANT);
return factory;
}
}
To MQ
#Configuration
public class MqConnectionConfig {
#Bean(name = Constants.CONNECTION_FACTORY_BEAN_NAME)
public MQConnectionFactory mqConnectionFactory() throws JMSException {
MQConnectionFactory mqConnectionFactory = new MQConnectionFactory();
mqConnectionFactory.setHostName(constants.getHost());
mqConnectionFactory.setPort(constants.getPort());
mqConnectionFactory.setQueueManager(constants.getManager());
mqConnectionFactory.setChannel(constants.getChannel());
mqConnectionFactory.setTransportType(constants.getTranspType());
return mqConnectionFactory;
}
#Bean(name = Constants.CACHING_CONNECTION_FACTORY_BEAN_NAME)
public CachingConnectionFactory cachingConnectionFactory(
#Qualifier(Constants.CONNECTION_FACTORY_BEAN_NAME) MQConnectionFactory mqConnectionFactory)
throws JMSException {
CachingConnectionFactory cachingConnectionFactory =
new CachingConnectionFactory(mqConnectionFactory());
cachingConnectionFactory.setSessionCacheSize(10);
return cachingConnectionFactory;
}
#Bean(name = Constants.TEMPLATE_BEAN_NAME)
public JmsTemplate jmsTemplate(
#Qualifier(Constants.CONNECTION_FACTORY_BEAN_NAME) CachingConnectionFactory cachingConnectionFactory)
throws JMSException {
JmsTemplate jmsTemplate = new JmsTemplate(cachingConnectionFactory);
jmsTemplate.setDefaultDestinationName(constants.getMqDestiQueue);
jmsTemplate.setReceiveTimeout(constants.getTimeout());
jmsTemplate.setDeliveryMode(constants.getDeliveryMode());
jmsTemplate.setSessionAcknowledgeModeName(constants.getSessionMode());
jmsTemplate.setExplicitQosEnabled(true);
jmsTemplate.setSessionTransacted(false);
return jmsTemplate;
}
#Bean(name = Constants.EMS_LISTENER_BEAN_NAME)
public DefaultJmsListenerContainerFactory mqJmsListenerContainerFactory(
#Qualifier(Constants.CACHING_CONNECTION_FACTORY_BEAN_NAME) CachingConnectionFactory cachingConnectionFactory,
GenericEmsErrorHandler genericIbmErrorHandler) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(cachingConnectionFactory);
factory.setErrorHandler(genericIbmErrorHandler);
factory.setConcurrency(Constants.CONCURRENT_CONSTANT);
return factory;
}
}
and when I running the app sends me this error
ErrorHandler, unmanaged exception description: Listener method Consumer.consumerProcess(java.lang.String,java.lang.String)'
threw exception; nested exception is org.springframework.jms.InvalidDestinationException: Not allowed to create destination;
nested exception is javax.jms.InvalidDestinationException: Not allowed to create destination.
Can anyone help me? What is wrong?
I have no idea how to fix the error

#JmsListener to listen multiple topics is listening to only one topic

I have two #jmsListeners in a class in my spring boot application .Both are listening to ActiveMQ TOPICs.But It listens only one topic not both.Need help
#JmsListener(destination = "${foo1}", containerFactory = "foo1Factory")
public void onmessage(final Message message) throws JMSException, InvalidProtocolBufferException {
sysout("Received status message: {}", message);
}
#JmsListener(destination = "${foo2}", containerFactory = "foo2Factory")
public void onmessage(final Message message) throws JMSException, InvalidProtocolBufferException {
sysout("Received status message: {}", message);
}
//JMS Configuration:
#Bean
public ConnectionFactory connectionFactory() {
ActiveMQConnectionFactory connectionFactory = new
ActiveMQConnectionFactory();
connectionFactory.setBrokerURL(brokerUrl);
connectionFactory.setUserName(userName);
connectionFactory.setPassword(password);
return connectionFactory;
}
#Bean(name = "foo1Factory")
public DefaultJmsListenerContainerFactory QueueOUTFactory(ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setPubSubDomain(true);
factory.setConcurrency("1-2");
configurer.configure(factory, connectionFactory);
return factory;
}
#Bean(name = "foo2Factory")
public DefaultJmsListenerContainerFactory QueueOUTFactory1(ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setPubSubDomain(true);
factory.setConcurrency("1-2");
configurer.configure(factory, connectionFactory);
return factory;
}

Spring JMS Configuration using JNDI

I am trying to load queue connection factory configurations using JNDI into My application which works fine when we use Queue Manager(IBM Websphere MQ) which is not secured. But when we changed to secured Queue Manager the same JNDI look up does not work. I am adding the logic used for JNDI look up below.
public class EpsJmsConfig {
#Bean
public JndiObjectFactoryBean connectionFactoryBean() {
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setJndiName("jms/NotificationCF");
bean.setResourceRef(false);
return bean;
}
#Bean
public ConnectionFactory connectionFactory() {
return (ConnectionFactory) connectionFactoryBean().getObject();
}
#Bean
public JndiObjectFactoryBean epsXiBillPayNotificationDestinationBean() {
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setJndiName("jms/epsXiBillPayNotificationQ");
return bean;
}
#Bean
public Destination epsXiBillPayNotificationDestination() {
return (Destination) epsXiBillPayNotificationDestinationBean().getObject();
}
#Bean(name = "xiBillpayNotificationJmsTemplate")
public JmsTemplate xiBillpayNotificationJmsTemplate() {
JmsTemplate jmsTemplate = new JmsTemplate();
jmsTemplate.setConnectionFactory(connectionFactory());
jmsTemplate.setDefaultDestination(epsXiBillPayNotificationDestination());
return jmsTemplate;
}
}

Spring application in WebSphere. Setup of JMS message listener invoker failed

I have a spring application deplyoed in WebSphere container and I need to configure JMS but I have a problem. Sending messages works fine but MessageListener doesn't consumes messages.
This is my jms config:
#Bean
public PlatformTransactionManager transactionManager() {
return new WebSphereUowTransactionManager();
}
#Bean
public ConnectionFactory jmsConnectionFactory() throws NamingException {
return jndi().lookup(CONNECTION_FACTORY_ADDRESS, ConnectionFactory.class);
}
#Bean(name = "queue")
public Queue jmsQueue() throws NamingException {
return jndi().lookup(QUEUE_ADDRESS, Queue.class);
}
#Bean(name = "replyQueue")
public Queue jmsReplyQueue() throws NamingException {
return jndi().lookup(REPLY_QUEUE_ADDRESS, Queue.class);
}
#Bean
public DestinationResolver jmsDestinationResolver() {
return new JndiDestinationResolver();
}
#Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() throws NamingException {
final DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(jmsConnectionFactory());
factory.setDestinationResolver(jmsDestinationResolver());
factory.setTransactionManager(transactionManager());
factory.setSessionTransacted(true);
factory.setConcurrency("3-10");
factory.setTaskExecutor(threadPoolTaskExecutor());
return factory;
}
#Bean
public TaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(50);
executor.setKeepAliveSeconds(20);
return executor;
}
I get this exception on startup:
[08.06.17 18:23:38:765 MSK] 00000409 DefaultMessag W org.springframework.jms.listener.DefaultMessageListenerContainer handleListenerSetupFailure Setup of JMS message listener invoker failed for destination 'jms/test_queue' - trying to recover. Cause: No JTA UserTransaction available - programmatic PlatformTransactionManager.getTransaction usage not supported
I read that It can be cause of the conflict with hibernate transitive dependency. I've tried to exclude jboss-transaction-api_1.1_spec dependency from hibernate-core but it didn't help.
I've also tried to use WorkManagerTaskExecutor:
#Bean
public TaskExecutor taskExecutor() {
WorkManagerTaskExecutor executor = new WorkManagerTaskExecutor();
executor.setWorkManagerName("wm/default");
return executor;
}
But exception is still throws.
What could be the problem?

Categories