I'm creating a Publisher Spring boot application to test sending an Account object using jmsTemplate.convertAndSend(destination, account); to a Consumer Spring boot application I created.
In my pom.xml I have the following <dependencies> and <plugin> setup which lets maven-jaxb2-plugin generate the Java object from the xsd folder I created.
pom.xml
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-artemis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-oxm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<!-- user-added -->
<plugin>
<!-- https://mvnrepository.com/artifact/org.jvnet.jaxb2.maven2/maven-jaxb2-plugin -->
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.15.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaDirectory>${project.basedir}/src/main/resources/xsd</schemaDirectory>
<schemaIncludes>
<include>*.xsd</include>
</schemaIncludes>
</configuration>
</plugin>
</plugins>
</build>
MessageProducerApplication
import java.io.InputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jms.core.JmsTemplate;
import com.example.xmlns.Account;
@SpringBootApplication
public class MessageProducerApplication implements CommandLineRunner {
private static final Logger LOGGER = LoggerFactory.getLogger(MessageProducerApplication.class.getName());
@Autowired
private JmsTemplate jmsTemplate;
@Value("${outbound.queue}")
private String destination; // outbound queue
public static void main(String[] args) {
SpringApplication.run(MessageProducerApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
ClassPathResource xmlResource = new ClassPathResource("xml/accountcreate.xml");
InputStream xmlStream = ClassLoader.getSystemResourceAsStream(xmlResource.getPath());
File xmlFile = new File("src/main/resources/xml/accountcreate.xml");
try {
JAXBContext jaxbContext = JAXBContext.newInstance(Account.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Account account = (Account) jaxbUnmarshaller.unmarshal(xmlFile);
//Account account = (Account) jaxbUnmarshaller.unmarshal(xmlStream);
jmsTemplate.convertAndSend(destination, account);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Problem
The conversion to Account type fails in this line:
Account account = (Account) jaxbUnmarshaller.unmarshal(xmlFile);
Exception
org.springframework.jms.support.converter.MessageConversionException: Cannot convert object of type [com.example.xmlns.Account] to JMS message. Supported message payloads are: String, byte array, Map<String,?>, Serializable object.
at org.springframework.jms.support.converter.SimpleMessageConverter.toMessage(SimpleMessageConverter.java:79) ~[spring-jms-5.3.19.jar:5.3.19]
The Account.java class was generated by xjc (both my Producer and Consumer application has the same Account class)
@XmlRootElement(name = "account")
public class Account {
@XmlElement(required = true)
//fields....
}
In my Consumer application, I set the listener to receive a type of Account
@Component
public class MessageListener {
private static final Logger LOGGER = LoggerFactory.getLogger(MessageListener.class);
@JmsListener(destination = "${inbound.queue}")
public void onMessage(Account account) {
LOGGER.info("account"+account);
}
}
I'd appreciate any thoughts or suggestion. Thanks.
Okay, after reviewing my code I found the reason why it's failing to cast to
Accountafter unmarshal(). I realized, I wasn't using theJaxb2Marshallerthat I configured with aMarshallingMessageConverterin my@Configurationclass.The changes to be made on
MessageProducerApplicationclass are as followsThen add the configuration class
I hope this would help others who might encounter the same problem.