I am after sending/receiving call to JMS queue synchronously using JMS Template and Spring boot. I went through official spring doc for JMS template but of no help.
I am not too sure about calling receive() method specifically or it will automatically receive message once send() is invoked. Since this is synchronous call I only need to receive message that I've sent (with the correlation Id).
Any help in this regard would be appreciated. Please let me know if you need any further info.
Update!!
Below is my spring boot code.
JMSSConfig.java
@Configuration
@EnableJms
public class JMSConfig {
@Bean
public JmsListenerContainerFactory<?> myFactory(ConnectionFactory connectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
// This provides all boot's default to this factory, including the message converter
configurer.configure(factory, connectionFactory);
// You could still override some of Boot's default if necessary.
return factory;
}
@Bean
public MarshallingMessageConverter createMarshallingMessageConverter(final Jaxb2Marshaller jaxb2Marshaller) {
System.out.println("executing createMarshallingMessageConverter");
return new MarshallingMessageConverter(jaxb2Marshaller);
}
@Bean
public Jaxb2Marshaller createJaxb2Marshaller(@Value("${context.path}") final String contextPath, @Value("${schema.location}") final String schemaLocaation) {
System.out.println("executing Jaxb2Marshaller");
Resource schemaResource = new ClassPathResource(schemaLocaation);
Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
jaxb2Marshaller.setContextPath(contextPath);
jaxb2Marshaller.setSchema(schemaResource);
Map<String, Object> properties = new HashMap<>();
properties.put(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxb2Marshaller.setMarshallerProperties(properties);
return jaxb2Marshaller;
}
}
Sender and receiver code
@Component
public class Receiver {
@Autowired
JmsTemplate jmsTemplate;
@JmsListener(destination = "mailbox", containerFactory="myFactory")
public void receiveMessage(CacheMsgType submitEventType) {
System.out.println("Received <" + submitEventType + ">");
}
public void send(CacheMsgType submitEventType) {
jmsTemplate.convertAndSend("mailbox", submitEventType);
System.out.println("Successfully sent a message.");
}
}
JAXB Generated classes
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "SubmitEventType", namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", propOrder = {
"eventType",
"clientApplication",
"clientReferenceID",
"systemDate",
"transactionAcceptTime",
"bsb",
"accountNumber",
"productcode",
"accttypecode",
"trancode",
"meid",
"baiCode",
"baiDecs",
"tranamount",
"amountonhold",
"recordedlimit",
"currentbalance",
"availablebalance",
"description",
"reference",
"payer"
})
public class SubmitEventType {
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String eventType;
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String clientApplication;
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String clientReferenceID;
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String systemDate;
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String transactionAcceptTime;
@XmlElement(name = "BSB", namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String bsb;
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String accountNumber;
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String productcode;
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String accttypecode;
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String trancode;
@XmlElement(name = "MEID", namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String meid;
@XmlElement(name = "BAICode", namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String baiCode;
@XmlElement(name = "BAIDecs", namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String baiDecs;
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String tranamount;
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String amountonhold;
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String recordedlimit;
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String currentbalance;
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String availablebalance;
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String description;
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String reference;
@XmlElement(namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected String payer;
/**
* Gets the value of the eventType property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getEventType() {
return eventType;
}
/**
* Sets the value of the eventType property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setEventType(String value) {
this.eventType = value;
}
/**
* Gets the value of the clientApplication property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getClientApplication() {
return clientApplication;
}
/**
* Sets the value of the clientApplication property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setClientApplication(String value) {
this.clientApplication = value;
}
/**
* Gets the value of the clientReferenceID property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getClientReferenceID() {
return clientReferenceID;
}
/**
* Sets the value of the clientReferenceID property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setClientReferenceID(String value) {
this.clientReferenceID = value;
}
/**
* Gets the value of the systemDate property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getSystemDate() {
return systemDate;
}
/**
* Sets the value of the systemDate property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setSystemDate(String value) {
this.systemDate = value;
}
/**
* Gets the value of the transactionAcceptTime property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getTransactionAcceptTime() {
return transactionAcceptTime;
}
/**
* Sets the value of the transactionAcceptTime property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setTransactionAcceptTime(String value) {
this.transactionAcceptTime = value;
}
/**
* Gets the value of the bsb property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getBSB() {
return bsb;
}
/**
* Sets the value of the bsb property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setBSB(String value) {
this.bsb = value;
}
/**
* Gets the value of the accountNumber property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getAccountNumber() {
return accountNumber;
}
/**
* Sets the value of the accountNumber property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setAccountNumber(String value) {
this.accountNumber = value;
}
/**
* Gets the value of the productcode property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getProductcode() {
return productcode;
}
/**
* Sets the value of the productcode property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setProductcode(String value) {
this.productcode = value;
}
/**
* Gets the value of the accttypecode property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getAccttypecode() {
return accttypecode;
}
/**
* Sets the value of the accttypecode property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setAccttypecode(String value) {
this.accttypecode = value;
}
/**
* Gets the value of the trancode property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getTrancode() {
return trancode;
}
/**
* Sets the value of the trancode property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setTrancode(String value) {
this.trancode = value;
}
/**
* Gets the value of the meid property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getMEID() {
return meid;
}
/**
* Sets the value of the meid property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setMEID(String value) {
this.meid = value;
}
/**
* Gets the value of the baiCode property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getBAICode() {
return baiCode;
}
/**
* Sets the value of the baiCode property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setBAICode(String value) {
this.baiCode = value;
}
/**
* Gets the value of the baiDecs property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getBAIDecs() {
return baiDecs;
}
/**
* Sets the value of the baiDecs property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setBAIDecs(String value) {
this.baiDecs = value;
}
/**
* Gets the value of the tranamount property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getTranamount() {
return tranamount;
}
/**
* Sets the value of the tranamount property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setTranamount(String value) {
this.tranamount = value;
}
/**
* Gets the value of the amountonhold property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getAmountonhold() {
return amountonhold;
}
/**
* Sets the value of the amountonhold property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setAmountonhold(String value) {
this.amountonhold = value;
}
/**
* Gets the value of the recordedlimit property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getRecordedlimit() {
return recordedlimit;
}
/**
* Sets the value of the recordedlimit property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setRecordedlimit(String value) {
this.recordedlimit = value;
}
/**
* Gets the value of the currentbalance property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getCurrentbalance() {
return currentbalance;
}
/**
* Sets the value of the currentbalance property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setCurrentbalance(String value) {
this.currentbalance = value;
}
/**
* Gets the value of the availablebalance property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getAvailablebalance() {
return availablebalance;
}
/**
* Sets the value of the availablebalance property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setAvailablebalance(String value) {
this.availablebalance = value;
}
/**
* Gets the value of the description property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getDescription() {
return description;
}
/**
* Sets the value of the description property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setDescription(String value) {
this.description = value;
}
public String getReference() {
return reference;
}
public void setReference(String value) {
this.reference = value;
}
public String getPayer() {
return payer;
}
public void setPayer(String value) {
this.payer = value;
}
}
CashMsgType.java
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlRootElement(name = "CacheMsg", namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "CacheMsgType", namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", propOrder = {
"submitEvent"
})
public class CacheMsgType {
@XmlElement(name = "SubmitEvent", namespace = "nabgroup.com/nab/schema/PaymentsExecution/SubmitPaymentEvent", required = true)
protected List<SubmitEventType> submitEvent;
public List<SubmitEventType> getSubmitEvent() {
if (submitEvent == null) {
submitEvent = new ArrayList<SubmitEventType>();
}
return this.submitEvent;
}
}
It seems sending on to mailbox queue is working but receiving gives error
Exception
2018-05-05 10:44:53.280 WARN 4120 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer : Execution of JMS message listener failed, and no ErrorHandler has been set.
org.springframework.jms.listener.adapter.ListenerExecutionFailedException: Listener method could not be invoked with incoming message Endpoint handler details: Method [public void com.nab.services.mq.Receiver.receiveMessage(com.nab.services.dto.CacheMsgType)] Bean [com.nab.services.mq.Receiver@134bfc8] ; nested exception is org.springframework.messaging.converter.MessageConversionException: Cannot convert from [javax.xml.bind.JAXBElement] to [com.nab.services.dto.CacheMsgType] for org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter$LazyResolutionMessage@3621aa, failedMessage=org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter$LazyResolutionMessage@3621aa at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:118) ~[spring-jms-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:77) ~[spring-jms-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:736) ~[spring-jms-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:696) ~[spring-jms-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:674) ~[spring-jms-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:318) [spring-jms-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:257) [spring-jms-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1189) [spring-jms-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1179) [spring-jms-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1076) [spring-jms-5.0.5.RELEASE.jar:5.0.5.RELEASE] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_162] Caused by: org.springframework.messaging.converter.MessageConversionException: Cannot convert from [javax.xml.bind.JAXBElement] to [com.nab.services.dto.CacheMsgType] for org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter$LazyResolutionMessage@3621aa at org.springframework.messaging.handler.annotation.support.PayloadArgumentResolver.resolveArgument(PayloadArgumentResolver.java:144) ~[spring-messaging-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:116) ~[spring-messaging-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:137) ~[spring-messaging-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:109) ~[spring-messaging-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:114) ~[spring-jms-5.0.5.RELEASE.jar:5.0.5.RELEASE] ... 10 common frames omitted