Can't subscribe a durable topic with Solace JMS - jms

I'd like to subscribe a durable topic using Solace JMS API. But when I start my application, it thrown below error:
[Context_3_ReactorThread] INFO com.solacesystems.jcsmp.impl.flow.BindRequestTask - Error Response (503) - Max clients exceeded for durable topic endpoint
I use the latest docker image of solace on centos 7. the image version is solace-pubsub-standard (9.1.0.201).
Below is my code:
#Bean
public SolConnectionFactory connectionFactory() {
SolConnectionFactory connectionFactory = new SolConnectionFactoryImpl();
connectionFactory.setHost("10.69.94.182");
connectionFactory.setUsername("default");
connectionFactory.setPassword("default");
connectionFactory.setVPN("default");
connectionFactory.setDynamicDurables(true);
return connectionFactory;
}
#Bean
public DefaultJmsListenerContainerFactory pubSubContainerFactory(ConnectionFactory connectionFactory) {
DefaultJmsListenerContainerFactory listenerContainerFactory = new DefaultJmsListenerContainerFactory();
listenerContainerFactory.setConnectionFactory(connectionFactory);
listenerContainerFactory.setPubSubDomain(true);
listenerContainerFactory.setSubscriptionDurable(true);
return listenerContainerFactory;
}
#JmsListener(destination = "com.schindler.ioee.gdcs.Callback", containerFactory = "pubSubContainerFactory")
public void processCallback(Message message) {
/*message.getHeaders().entrySet().forEach(item -> log.info("{}:{}", item.getKey(), item.getValue()));*/
log.info("[CONSUMER] topic={}, message={}", message.getHeaders().get("jms_destination"), message.getPayload());
}
I tried to set the max-bind-count for the topic endpoint to 1024, it also throw the above error.
Can any one provide some help. Thank you in advance!

The problem was resolved after reading the document https://docs.solace.com/Solace-JMS-API/Creating-Durable-Topic-S.htm.
I have 2 subscription, and I missed to add a subscription in the annotation. If the subscription name is missing, spring will use the default name "org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter" as the subscription name. According to the document, one session can't subscribe the same topic endpoint twice. So an error was thrown.
My finally consumer code looks like below:
#Component
#Slf4j
public class MessageConsumer {
#JmsListener(destination = "com.schindler.ioee.gdcs.Callback", containerFactory = "pubSubContainerFactory", subscription = "com.schindler.ioee.gdcs.Callback")
public void processCallback(Message message) {
// message.getHeaders().entrySet().forEach(item -> log.info("{}:{}", item.getKey(), item.getValue()));
log.info("[CONSUMER] topic={}, message={}", message.getHeaders().get("jms_destination"), message.getPayload());
}
#JmsListener(destination = "com.schindler.ioee.gdcs.Symptom", containerFactory = "pubSubContainerFactory", subscription = "com.schindler.ioee.gdcs.Symptom")
public void processSymptom(Message message) {
// message.getHeaders().entrySet().forEach(item -> log.info("{}:{}", item.getKey(), item.getValue()));
log.info("[CONSUMER] topic={}, message={}", message.getHeaders().get("jms_destination"), message.getPayload());
}
#JmsListener(destination = "com.schindler.ioee.gdcs.Equipment", containerFactory = "pubSubContainerFactory", subscription = "com.schindler.ioee.gdcs.Equipment")
public void processEquipment(Message message) {
// message.getHeaders().entrySet().forEach(item -> log.info("{}:{}", item.getKey(), item.getValue()));
log.info("[CONSUMER] topic={}, message={}", message.getHeaders().get("jms_destination"), message.getPayload());
}
#JmsListener(destination = "t/cn/rtc/*/status", subscription = "sms_mqtt_subscription", containerFactory = "pubSubContainerFactory")
public void processStatus(Message message) {
// message.getHeaders().entrySet().forEach(item -> log.info("{}:{}", item.getKey(), item.getValue()));
log.info("[CONSUMER] topic={}, message={}", message.getHeaders().get("jms_destination"), new String((byte[]) message.getPayload()));
}
}

Related

How to properly configure multiple DMLCs to listen to a single sqs queue?

We have an order managament system in which after every order state update we make an api call to our client to keep them updated. We do this by first sending a message to a sqs queue and inside a consumer we hit our clients api. The processing on consumer side usually takes about 300-350ms but The approximate age of oldest message in sqs dashboard is showing spikes that reach upto 50-60 secs.
Seeing this I thought that maybe one consumer is not enough for our load and I created multiple DMLC beans and multiple copies of our consumer class. I attached these consumer classes as listeners in these DMLCs. But I have not seen any improvement in approximate age of oldest message.
I am guessing that maybe only one of the DMLC is processing these messages and others are just sitting idle.
I added multiple DMLCs because there are other places in pur codebase where the same thing is used, But now I am not sure if this is the correct way to solve the problem.
My Consumer class looks like this:
#Component
#Slf4j
#RequiredArgsConstructor
public class HOAEventsOMSConsumer extends ConsumerCommon implements MessageListener {
private static final int MAX_RETRY_LIMIT = 3;
private final OMSEventsWrapper omsEventsWrapper;
#Override
public void onMessage(Message message) {
try {
TextMessage textMessage = (TextMessage) message;
String jmsMessageId = textMessage.getJMSMessageID();
ConsumerLogging.logStart(jmsMessageId);
String text = textMessage.getText();
log.info(
"Inside HOA Events consumer Request jmsMessageId:- " + jmsMessageId + " Text:- "
+ text);
processAndAcknowledge(message, text, textMessage);
} catch (JMSException e) {
log.error("JMS Exception while processing surge message", e);
}
}
private void processAndAcknowledge(Message message, String text, TextMessage textMessage) throws JMSException {
try {
TrimmedHOAEvent hoaEvent = JsonHelper.convertFromJsonPro(text, TrimmedHOAEvent.class);
if (hoaEvent == null) {
throw new OMSValidationException("Empty message in hoa events queue");
}
EventType event = EventType.fromString(textMessage.getStringProperty("eventType"));
omsEventsWrapper.handleOmsEvent(event,hoaEvent);
acknowledgeMessage(message);
} catch (Exception e) {
int retryCount = message.getIntProperty("JMSXDeliveryCount");
log.info("Retrying... retryCount: {}, HOAEventsOMSConsumer: {}", retryCount, text);
if (retryCount > MAX_RETRY_LIMIT) {
log.info("about to acknowledge the message since it has exceeded maximum retry limit");
acknowledgeMessage(message);
}
}
}
}
And my DMLC configuration class looks like this:
#Configuration
#SuppressWarnings("unused")
public class HOAEventsOMSJMSConfig extends JMSConfigCommon{
private Boolean isSQSQueueEnabled;
#Autowired
private HOAEventsOMSConsumer hoaEventsOMSConsumer;
#Autowired
private HOAEventsOMSConsumer2 hoaEventsOMSConsumer2;
#Autowired
private HOAEventsOMSConsumer3 hoaEventsOMSConsumer3;
#Autowired
private HOAEventsOMSConsumer4 hoaEventsOMSConsumer4;
#Autowired
private HOAEventsOMSConsumer5 hoaEventsOMSConsumer5;
#Autowired
private HOAEventsOMSConsumer6 hoaEventsOMSConsumer6;
#Autowired
private HOAEventsOMSConsumer7 hoaEventsOMSConsumer7;
#Autowired
private HOAEventsOMSConsumer8 hoaEventsOMSConsumer8;
#Autowired
private HOAEventsOMSConsumer9 hoaEventsOMSConsumer9;
#Autowired
private HOAEventsOMSConsumer10 hoaEventsOMSConsumer10;
public HOAEventsOMSJMSConfig(IPropertyService propertyService, Environment env) {
queueName = env.getProperty("aws.sqs.queue.oms.hoa.events.queue");
endpoint = env.getProperty("aws.sqs.queue.endpoint") + queueName;
JMSConfigCommon.accessId = env.getProperty("aws.sqs.access.id");
JMSConfigCommon.accessKey = env.getProperty("aws.sqs.access.key");
try {
ServerNameCache serverNameCache = CacheManager.getInstance().getCache(ServerNameCache.class);
if (serverNameCache == null) {
serverNameCache = new ServerNameCache();
serverNameCache.set(InetAddress.getLocalHost().getHostName());
CacheManager.getInstance().setCache(serverNameCache);
}
this.isSQSQueueEnabled = propertyService.isConsumerEnabled(serverNameCache.get(), false);
} catch (Exception e) {
this.isSQSQueueEnabled = false;
}
}
#Bean
public JmsTemplate omsHOAEventsJMSTemplate(){
SQSConnectionFactory sqsConnectionFactory;
if (endpoint.toLowerCase().contains("localhost")) {
sqsConnectionFactory =
SQSConnectionFactory.builder().withEndpoint(getEndpoint("sqs")).build();
} else {
sqsConnectionFactory = SQSConnectionFactory.builder()
.withAWSCredentialsProvider(awsCredentialsProvider)
.withNumberOfMessagesToPrefetch(10)
.withEndpoint(endpoint)
.build();
}
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(sqsConnectionFactory);
JmsTemplate jmsTemplate = new JmsTemplate(cachingConnectionFactory);
jmsTemplate.setDefaultDestinationName(queueName);
jmsTemplate.setDeliveryPersistent(false);
jmsTemplate.setSessionTransacted(false);
jmsTemplate.setSessionAcknowledgeMode(SQSSession.UNORDERED_ACKNOWLEDGE);
return jmsTemplate;
}
#Bean
public DefaultMessageListenerContainer jmsListenerHOAEventsListenerContainer() {
SQSConnectionFactory sqsConnectionFactory;
if (endpoint.toLowerCase().contains("localhost")) {
sqsConnectionFactory = SQSConnectionFactory.builder()
.withEndpoint(getEndpoint("sqs"))
.build();
} else {
sqsConnectionFactory = SQSConnectionFactory.builder()
.withAWSCredentialsProvider(awsCredentialsProvider)
.withNumberOfMessagesToPrefetch(10)
.withEndpoint(endpoint)
.build();
}
DefaultMessageListenerContainer dmlc = new DefaultMessageListenerContainer();
dmlc.setConnectionFactory(sqsConnectionFactory);
dmlc.setDestinationName(queueName);
dmlc.setAutoStartup(isSQSQueueEnabled);
dmlc.setMessageListener(hoaEventsOMSConsumer);
dmlc.setSessionTransacted(false);
dmlc.setSessionAcknowledgeMode(SQSSession.UNORDERED_ACKNOWLEDGE);
return dmlc;
}
#Bean
public DefaultMessageListenerContainer jmsListenerHOAEventsListenerContainerNo2() {
SQSConnectionFactory sqsConnectionFactory;
if (endpoint.toLowerCase().contains("localhost")) {
sqsConnectionFactory = SQSConnectionFactory.builder()
.withEndpoint(getEndpoint("sqs"))
.build();
} else {
sqsConnectionFactory = SQSConnectionFactory.builder()
.withAWSCredentialsProvider(awsCredentialsProvider)
.withNumberOfMessagesToPrefetch(10)
.withEndpoint(endpoint)
.build();
}
DefaultMessageListenerContainer dmlc = new DefaultMessageListenerContainer();
dmlc.setConnectionFactory(sqsConnectionFactory);
dmlc.setDestinationName(queueName);
dmlc.setAutoStartup(isSQSQueueEnabled);
dmlc.setMessageListener(hoaEventsOMSConsumer2);
dmlc.setSessionTransacted(false);
dmlc.setSessionAcknowledgeMode(SQSSession.UNORDERED_ACKNOWLEDGE);
return dmlc;
}
#Bean
public DefaultMessageListenerContainer jmsListenerHOAEventsListenerContainerNo3() {
SQSConnectionFactory sqsConnectionFactory;
if (endpoint.toLowerCase().contains("localhost")) {
sqsConnectionFactory = SQSConnectionFactory.builder()
.withEndpoint(getEndpoint("sqs"))
.build();
} else {
sqsConnectionFactory = SQSConnectionFactory.builder()
.withAWSCredentialsProvider(awsCredentialsProvider)
.withNumberOfMessagesToPrefetch(10)
.withEndpoint(endpoint)
.build();
}
DefaultMessageListenerContainer dmlc = new DefaultMessageListenerContainer();
dmlc.setConnectionFactory(sqsConnectionFactory);
dmlc.setDestinationName(queueName);
dmlc.setAutoStartup(isSQSQueueEnabled);
dmlc.setMessageListener(hoaEventsOMSConsumer3);
dmlc.setSessionTransacted(false);
dmlc.setSessionAcknowledgeMode(SQSSession.UNORDERED_ACKNOWLEDGE);
return dmlc;
}
}
If this question is already answered somehwere else, then please point me towards that.

How can i intercept incomig messages before they reach methods annotated with #RabbitListener?

I Started by setting up an interceptor for outgoing messages which is working smoothly, but
when i try to intercept incomming messages in the consumers, the postProcessMessage method
is skipped and the message reaches the method annotated with #RabbitListener, bellow is my code for the whole proccess, i ommited unimportant code.
Producer
RabbitMQProducerInterceptor
#Component
#Slf4j
public class RabbitMQProducerInterceptor implements MessagePostProcessor {
#Override
public Message postProcessMessage(Message message) throws AmqpException {
log.info("Getting the current HttpServletRequest");
HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
log.info("Extracting the X-REQUEST-ID from the header of the HttpServletRequest");
String XRequestId = req.getHeader(ShareableConstants.X_REQUEST_ID_HEADER);
log.info("Adding X-REQUEST-ID {} to the RabbitMQ Producer Header", XRequestId);
message.getMessageProperties().getHeaders().put(ShareableConstants.X_REQUEST_ID_HEADER, XRequestId);
return message;
}
}
RabbitMQProducerConfig
#Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setReplyTimeout(60000);
MessagePostProcessor[] processors = {new RabbitMQProducerInterceptor()};
rabbitTemplate.addBeforePublishPostProcessors(processors);
return rabbitTemplate;
}
Sending a message to the consumer
User Producer
public UserRegistrationResponseDTO register(UserRegistrationDTO userRegistrationDTO) {
log.info("Sending user registration request {}", userRegistrationDTO);
UserRegistrationDTO response = (UserRegistrationDTO) rabbitTemplate
.convertSendAndReceive(ShareableConstants.EXCHANGE_NAME,
ShareableConstants.CREATE_USER_ROUTING_KEY,
userRegistrationDTO);
return UserRegistrationResponseDTO.builder()
.username(response.getUsername())
.id(response.getId())
.createdAt(response.getCreatedAt()).build();
}
Consumer
RabbitMQConsumerConfig
#Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
MessagePostProcessor[] processors = {new RabbitMQConsumerInterceptor()};
rabbitTemplate.setAfterReceivePostProcessors(processors);
return rabbitTemplate;
}
RabbitMQConsumerInterceptor
#Component
public class RabbitMQConsumerInterceptor implements MessagePostProcessor {
#Override
public Message postProcessMessage(Message message) throws AmqpException {
String XRequestId = message.getMessageProperties().getHeader(ShareableConstants.X_REQUEST_ID_HEADER);
MDC.put(ShareableConstants.X_REQUEST_ID_HEADER, XRequestId);
return message;
}
}
User Consumer
#RabbitListener(bindings =
#QueueBinding(exchange = #Exchange(ShareableConstants.EXCHANGE_NAME),
key = ShareableConstants.CREATE_USER_ROUTING_KEY,
value = #Queue(ShareableConstants.USER_REGISTRATION_QUEUE_NAME)))
public UserRegistrationDTO receiveUser(UserRegistrationDTO userRegistrationDTO) {
log.info("receiving user {} to register ", userRegistrationDTO);
User user = Optional.of(userRegistrationDTO).map(User::new).get();
User createdUser = userService.register(user);
UserRegistrationDTO registrationDTO = UserRegistrationDTO.builder()
.id(createdUser.getId())
.username(createdUser.getUsername())
.createdAt(createdUser.getCreationDate())
.build();
return registrationDTO;
}
Here's the code, no exception is thrown, the only problem is the Interceptor being skipped
The RabbitTemplate is not used to receive messages for a #RabbitListener; messages are received by a listener container; you have to set the afterReceivePostProcessors on the listener container factory.
If you are using Spring Boot, just add the auto-configured SimpleRabbitListenerContainerFactory as a parameter to one of your other #Beans and set the MPP on it.

Spring JMS listener acknowledge

I am using JMS to send receive message from IBM MQ message broker. I am currently working on listener service throwing unhandled excepion and message sent
back to queue without acknowledgement.
I want the service to retry a configurable number of time and throw meaning full exception message that listener service is unavailable.
My listener and container factory looks like below.
#JmsListener(destination = "testqueue", containerFactory = "queuejmsfactory")
public void consumer(String message) throws JMSException
{ handle(message); }
#Bean(name = "queuejmsfactory") public JmsListenerContainerFactory getQueueTopicFactory(ConnectionFactory con ,
DefaultJmsListenerContainerFactoryConfigurer config)
{ DefaultJmsListenerContainerFactory d = new DefaultJmsListenerContainerFactory();
d.setSessionTransacted(true);
d.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE);
config.configure(d,con);
return d; }
I short, I have an existing code using the SessionawareMessageListener onMessage which i am trying to
replicate to #JmsListener. How do i handle the session commit and rollback automatically and
how do i get the session in JmsListener if have to handle manually similar to onMessage.
#Override
public void onMessage(Mesage mes, Session ses) throws JMSException
{ try
{ TestMessage txtMessage = (TextMessage)message;
handle(txtMessage); ses.commit();
} catch (Exception exp)
{ if (shouldRollback(message))
{ ses.rollback();}
else{logger,warn("moved to dlq");
ses.commit();
}
} }
private boolean shouldRollback(Message mes) throws JMSException
{ int rollbackcount = mes.getIntProperty("JMSXDeliveryCount");
return (rollbackcount <= maxRollBackCountFromApplication.properties)
}
Updated code:
#JmsListener(destination = "testqueue", containerFactory = "queuejmsfactory")
public void consumer(Message message) throws JMSException
{
try {TestMessage txtMessage = (TextMessage)message;
handle(txtMessage);}
catch(Excepton ex) {
if shouldRollback(message)
{throw ex;}
else {logger.warn("moved to dlq")}
}}
private boolean shouldRollback(Message mes) throws JMSException
{ int rollbackcount = mes.getIntProperty("JMSXDeliveryCount");
return (rollbackcount <= maxRollBackCountFromApplication.properties)
}
#Bean(name = "queuejmsfactory") public JmsListenerContainerFactory getQueueTopicFactory(ConnectionFactory con ,
DefaultJmsListenerContainerFactoryConfigurer config)
{ DefaultJmsListenerContainerFactory d = new DefaultJmsListenerContainerFactory();
d.setSessionTransacted(true);
d.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE);
config.configure(d,con);
return d; }
I have also tried to access the JMSXDeliveryCount from Headers, but couldnt get the exact object to access delivery count. Can you clarify plz.
#JmsListener(destination = "testqueue", containerFactory = "queuejmsfactory")
public void consumer(Message message,
#Header(JmsHeaders.CORRELATION_ID) String correlationId,
#Header(name = "jms-header-not-exists") String nonExistingHeader,
#Headers Map<String, Object> headers,
MessageHeaders messageHeaders,
JmsMessageHeaderAccessor jmsMessageHeaderAccessor) {}
You can add the Session as another parameter to the JmsListener method.

aws sns to sqs, message not getting converted

I am trying to configure an SNS producer with SQS consumer, built with a Spring boot app. I have tried leveraging Spring cloud and just using JMS API, with both ways I cant seem to get my consumer to convert the message for me to read. With Spring cloud I get an error saying that the "payload is not a valid notification. Code below: Any help much appreciated
SNS configuration:
#Bean
public AmazonSNS snsClient() {
AmazonSNS snsClient = AmazonSNSClientBuilder.standard()
.withEndpointConfiguration(<endpoint-stuff)).build();
return snsClient;
}
#Bean
public NotificationMessagingTemplate notificationMessagingTemplate(
AmazonSNS amazonSNS) {
return new NotificationMessagingTemplate(amazonSNS);
}
producer code:
#Autowired
NotificationMessagingTemplate messagingTemplate;
public void send() throws Exception {
MessageDto message = new MessageDto();
message.setMessageA("Hello");
message.setMessageB("Again");
messagingTemplate.sendNotification("my_topic",message,"Test");
}
SQS consumer configuration:
#Bean
public SimpleMessageListenerContainer simpleMessageListenerContainer()
{
SimpleMessageListenerContainer msgListenerContainer =
simpleMessageListenerContainerFactory()
.createSimpleMessageListenerContainer();
msgListenerContainer.setMessageHandler(queueMessageHandler());
return msgListenerContainer;
}
#Bean
public SimpleMessageListenerContainerFactory
simpleMessageListenerContainerFactory() {
SimpleMessageListenerContainerFactory msgListenerContainerFactory =
new SimpleMessageListenerContainerFactory();
msgListenerContainerFactory.setAmazonSqs(amazonSQSClient());
return msgListenerContainerFactory;
}
#Bean
public QueueMessageHandler queueMessageHandler() {
QueueMessageHandlerFactory queueMsgHandlerFactory = new
QueueMessageHandlerFactory();
queueMsgHandlerFactory.setAmazonSqs(amazonSQSClient());
QueueMessageHandler queueMessageHandler =
queueMsgHandlerFactory.createQueueMessageHandler();
//List<HandlerMethodArgumentResolver> list = new ArrayList<>();
//HandlerMethodArgumentResolver resolver = new
//PayloadArgumentResolver(new MappingJackson2MessageConverter());
//list.add(resolver);
//queueMessageHandler.setArgumentResolvers(list);
return queueMessageHandler;
}
#Lazy
#Bean(name = "amazonSQS", destroyMethod = "shutdown")
public AmazonSQSAsync amazonSQSClient() {
AwsClientBuilder.EndpointConfiguration endpointConfiguration = new
AwsClientBuilder.EndpointConfiguration(
"<url>, "<region");
AmazonSQSAsync awsSQSAsync =
AmazonSQSAsyncClientBuilder.standard()
.withEndpointConfiguration(endpointConfiguration)
.build();
return awsSQSAsync;
}
SQS listener:
#SqsListener(value = "my_queue", deletionPolicy =
SqsMessageDeletionPolicy.ON_SUCCESS)
public void consume(final #NotificationMessage MessageDto event) {
LOGGER.info("Message received {}
{}",event.getMessageA(),event.getMessageB());
}
stack trace:
Caused by:
org.springframework.messaging.converter.MessageConversionException:
Payload: '<payload here>' is not a valid notification
at
org.springframework.cloud.aws.messaging.support.
converter.NotificationRequestConverter.fromMessage
(NotificationRequestConverter.java:69)
at

How to handle JmsException /How do I set the redeliveryPolicy in ActiveMQ?

Let see one scenario is there when jms send message to consumer and we have to save that to db,but when db is down we cant able to save that to db due to db server is down.So how to acknowledge jms to send message again?
This issue raised by many people.I resolved this using below code snippet.
#Configuration
public class AppConfiguration {
#Bean
public JmsListenerContainerFactory<?> jmsContainerFactory(DefaultJmsListenerContainerFactoryConfigurer configurer) {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
connectionFactory.setClientID(clientId);
connectionFactory.setBrokerURL(brokerUrl);
CachingConnectionFactory cf = new CachingConnectionFactory(connectionFactory);
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(cf);
factory.setSubscriptionDurable(true);
configurer.configure(factory, cf);
return factory;
}
}
#Component("ApprovalSubsCriber")
public class ApprovalSubscriber implements SessionAwareMessageListener<TextMessage> {
#Override
#JmsListener(destination = "topic/jmsReplyTest1", containerFactory = "jmsContainerFactory", subscription = "ApprovalSubsCriber")
public void onMessage(TextMessage message, Session session) throws JMSException {
// This is the received message
System.out.println("Receive: " + message.getText());
// Let's prepare a reply message - a "ACK" String
ActiveMQTextMessage textMessage = new ActiveMQTextMessage();
textMessage.setText("ACK");
System.out.println(session.getAcknowledgeMode());
if ("notexception".equals(message.getText())) {
session.commit();
} else {
session.rollback();//If exception comes
}
}
}

Resources