I have Spring Boot app that handles incoming ArtemisMQ
@JmsListener(destination = "work-started")
public fun workStarted(work: Work) {
handleNewWork(work)
}
I created MappingJackson2MessageConverter with default setup
@Bean
fun jacksonJmsMessageConverter(): MessageConverter? {
val converter = MappingJackson2MessageConverter()
converter.setTargetType(MessageType.OBJECT)
// I don't receive class type
converter.setTypeIdPropertyName("_type")
return converter
}
And application.properties
spring.artemis.mode=native
spring.artemis.host=localhost
spring.artemis.port=61616
spring.artemis.user=root
spring.artemis.password=root
I want Spring to parse message by the input object, in my case I have Work as an argument, which I expect to be parsed from json.
When I run it, I'm getting this error:
Caused by: org.springframework.jms.support.converter.MessageConversionException: Could not find type id property [_type] on message [null] from destination [ActiveMQQueue[work-started]]
at org.springframework.jms.support.converter.MappingJackson2MessageConverter.getJavaTypeForMessage(MappingJackson2MessageConverter.java:456) ~[spring-jms-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.jms.support.converter.MappingJackson2MessageConverter.fromMessage(MappingJackson2MessageConverter.java:232) ~[spring-jms-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener.extractMessage(AbstractAdaptableMessageListener.java:251) ~[spring-jms-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter.extractPayload(AbstractAdaptableMessageListener.java:476) ~[spring-jms-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter$LazyResolutionMessage.unwrapPayload(AbstractAdaptableMessageListener.java:543) ~[spring-jms-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter$LazyResolutionMessage.getPayload(AbstractAdaptableMessageListener.java:525) ~[spring-jms-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.messaging.handler.annotation.support.PayloadMethodArgumentResolver.resolveArgument(PayloadMethodArgumentResolver.java:116) ~[spring-messaging-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:117) ~[spring-messaging-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:148) ~[spring-messaging-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:116) ~[spring-messaging-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:114) ~[spring-jms-5.2.5.RELEASE.jar:5.2.5.RELEASE]
... 10 common frames omitted
It's looking for _type property which is missing.
I did a small hack to check if my idea is correct. Here I map name of destination to Class, so that it later parses. But it feels like super wrong way of doing it.
val converter = object : MappingJackson2MessageConverter() {
override fun getJavaTypeForMessage(message: Message): JavaType {
var clazz :Class<*>? = null
val jmsDestination = message.jmsDestination as ActiveMQQueue
when(jmsDestination.address) {
"work-started" -> {
clazz = Work::class.java
}
}
if(clazz == null) {
return super.getJavaTypeForMessage(message)
}
return jacksonObjectMapper().typeFactory.constructType(clazz)
}
}
How can I resolve this by method argument or some annotation?