I am working on a JMS Queue for a requirement on JBOSS AS 7.
I am banging my head against the wall :(
I end up getting this error for the queue. It works fine when all of this configuration is part of the applicationContext.xml. We are avoiding cml config and moving to java config. That is when the issue comes up. Please help!!!
Here is the Queue Config in standalone.xml:
<jms-queue name="ticketOrderQueue">
<entry name="queue/ticketOrderQueue"/>
</jms-queue>
Here is my java spring config class.
//JMS Configuration
#Bean
public ConnectionFactory jmsConnectionFactory() throws IllegalArgumentException, NamingException {
JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
jndiObjectFactoryBean.setJndiName("java:/ConnectionFactory");
jndiObjectFactoryBean.afterPropertiesSet(); //HERE
return (ConnectionFactory) jndiObjectFactoryBean.getObject();
}
#Bean
public Queue requestsQueue() throws IllegalArgumentException, NamingException {
JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
jndiObjectFactoryBean.setJndiName("queue/ticketOrderQueue");
jndiObjectFactoryBean.setProxyInterface(Queue.class);
jndiObjectFactoryBean.afterPropertiesSet();
logger.debug("The Quues is :" + jndiObjectFactoryBean.getObject());
return (Queue) jndiObjectFactoryBean.getObject();
}
#Bean
public JmsTemplate jmsTemplate() throws IllegalArgumentException, NamingException {
final JmsTemplate jmsTemplate = new JmsTemplate(jmsConnectionFactory());
jmsTemplate.setDefaultDestination(requestsQueue());
return jmsTemplate;
}
#Bean
public CustomerDetailedReportJMSListener queueMessageReceiver() {
return new CustomerDetailedReportJMSListener();
}
#Bean
public DefaultMessageListenerContainer jmsListenerContainer() throws IllegalArgumentException, NamingException {
DefaultMessageListenerContainer dmlc = new DefaultMessageListenerContainer();
dmlc.setConnectionFactory(jmsConnectionFactory());
dmlc.setDestination(requestsQueue());
MessageListenerAdapter listener = new MessageListenerAdapter();
listener.setDelegate(queueMessageReceiver());
listener.setDefaultListenerMethod("onMessage");
dmlc.setMessageListener(listener);
dmlc.setConcurrentConsumers(10);
dmlc.afterPropertiesSet();
dmlc.start();
return dmlc;
Well, after a lot of trial and errors, it turned out that my classpath was overloaded with the jms jars. Once I got rid of the extra ones, I no more got the error.
Related
I am trying to read a message from Solace. I am able to read message successfully, but suppose while reading/processing the message the app crashes. How can I read that message again? With my below code I am not able to read that message again. Below is my configuration:
#JmsListener(destination = "myqueue", containerFactory = "jmsContainer", concurrency = "5-10")
public void onMessage(Message msg) {
String message;
if (msg instanceof TextMessage) {
message = ((TextMessage) msg).getText();
LOG.info("In here START " + message) ;
Thread.sleep(60000); //I crash my app while thread is sleeping here
LOG.info("In here END " + msg.getJMSDestination() ) ;
}
public class SolaceConfig {
#Bean("solaceJndiTemplate")
public JndiTemplate solaceJndiTemplate() {
JndiTemplate solaceJndiTemplate = new JndiTemplate();
// setting user name /password ommitted for brevity
solaceJndiTemplate.setEnvironment(properties);
return solaceJndiTemplate;
}
#Bean
public JndiObjectFactoryBean solaceConnectionFactory(){
JndiObjectFactoryBean solaceConnectionFactory = new JndiObjectFactoryBean();
solaceConnectionFactory.setJndiTemplate(solaceJndiTemplate());
solaceConnectionFactory.setJndiName(getJndiName());
return solaceConnectionFactory;
}
#Primary
#Bean
public CachingConnectionFactory solaceCachedConnectionFactory(){
CachingConnectionFactory solaceCachedConnectionFactory = new CachingConnectionFactory();
solaceCachedConnectionFactory.setTargetConnectionFactory((ConnectionFactory)solaceConnectionFactory().getObject());
solaceCachedConnectionFactory.setSessionCacheSize(10);
return solaceCachedConnectionFactory;
}
#Bean
public JmsTemplate jmsTemplate() {
JmsTemplate jmsTemplate = new JmsTemplate(solaceCachedConnectionFactory());
jmsTemplate.setDeliveryPersistent(true);
jmsTemplate.setExplicitQosEnabled(true);
return jmsTemplate;
}
#Bean
public DefaultJmsListenerContainerFactory jmsContainer() {
DefaultJmsListenerContainerFactory container = new DefaultJmsListenerContainerFactory();
container.setConnectionFactory(solaceCachedConnectionFactory());
//container.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE);
return container;
}
When using the DMLC, you should enable transactions (set sessionTransacted) so that the acknowledgment is rolled back.
Otherwise, use a SimpleMessageListenerContainer instead.
See the javadocs https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jms/listener/DefaultMessageListenerContainer.html
It is strongly recommended to either set "sessionTransacted" to "true" or specify an external "transactionManager". See the AbstractMessageListenerContainer javadoc for details on acknowledge modes and native transaction options, as well as the AbstractPollingMessageListenerContainer javadoc for details on configuring an external transaction manager. Note that for the default "AUTO_ACKNOWLEDGE" mode, this container applies automatic message acknowledgment before listener execution, with no redelivery in case of an exception.
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
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.
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;
}
}
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?