I have the following...
@MessageMapping("/hello")
@SendTo("/topic/greetings")
@Throws(Exception::class)
fun greeting(message: TestMessage): Greeting {
However, when I run and send a message I get
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `org.gleason.love_monkey.model.TestMessage` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 2]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63) ~[jackson-databind-2.18.2.jar:2.18.2]
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1754) ~[jackson-databind-2.18.2.jar:2.18.2]
I tried changing to
fun greeting(message: Any): Greeting {
val jsonString: String
// Log the incoming message
if (message is ByteArray) {
jsonString = byteArrayToString(message)
} else {
jsonString = objectMapper.writeValueAsString(message)
}
logger.info("Received message: $jsonString")
And when I do that I see that it is byteEncoded but correct...
2025-01-31T18:40:40.006-05:00 INFO 49504 --- [love-monkey] [nboundChannel-1] o.g.l.controller.WebsocketController : Received message: {"name":"me"}
The frame was made using the process described here
The data class is
data class TestMessage(val name: String)
What am I missing how can I type the message and still use postman
I tried changing to
val jsonString: String
// Log the incoming message
if (message is ByteArray) {
jsonString = byteArrayToString(message)
} else {
jsonString = objectMapper.writeValueAsString(message)
}
logger.info("Received message: $jsonString")
// Log the JSON string before deserialization
logger.info("JSON string to be deserialized: ${jsonString.trim()}")
val testMessage: TestMessage = objectMapper.readValue(jsonString.trim(), TestMessage::class.java)
And when I debug into the object mapper it looks correct...
But it still throws
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `org.gleason.love_monkey.model.TestMessage` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 2]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63) ~[jackson-databind-2.18.2.jar:2.18.2]
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1754) ~[jackson-databind-2.18.2.jar:2.18.2]
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1379) ~[jackson-databind-2.18.2.jar:2.18.2]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1512) ~[jackson-databind-2.18.2.jar:2.18.2]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:348) ~[jackson-databind-2.18.2.jar:2.18.2]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185) ~[jackson-databind-2.18.2.jar:2.18.2]
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342) ~[jackson-databind-2.18.2.jar:2.18.2]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4917) ~[jackson-databind-2.18.2.jar:2.18.2]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3860) ~[jackson-databind-2.18.2.jar:2.18.2]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3828) ~[jackson-databind-2.18.2.jar:2.18.2]
at org.gleason.love_monkey.controller.WebsocketController.greeting(WebsocketController.kt:35) ~[main/:na]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:169) ~[spring-messaging-6.2.2.jar:6.2.2]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:119) ~[spring-messaging-6.2.2.jar:6.2.2]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.java:568) ~[spring-messaging-6.2.2.jar:6.2.2]
at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:530) ~[spring-messaging-6.2.2.jar:6.2.2]
at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:93) ~[spring-messaging-6.2.2.jar:6.2.2]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessageInternal(AbstractMethodMessageHandler.java:522) ~[spring-messaging-6.2.2.jar:6.2.2]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(AbstractMethodMessageHandler.java:457) ~[spring-messaging-6.2.2.jar:6.2.2]
at org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:152) ~[spring-messaging-6.2.2.jar:6.2.2]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]
Per the answer I tried updating to
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
...
private val objectMapper = ObjectMapper().registerKotlinModule()
...
val testMessage: TestMessage = objectMapper.readValue(jsonString.trim(), TestMessage::class.java)
But I still get...
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of
org.gleason.love_monkey.model.TestMessage
(although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator) at [Source: REDACTED (StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION
disabled); line: 1, column: 2]
Raw message
SEND
destination:/app/hello
content-length:19
content-type:application/json
{"name":"Me"}
If you use injected objectMapper
, check that its definition contains registration of the Kotlin module.
So it should be like this
@Bean
fun objectMapper() = ObjectMapper().registerKotlinModule()
In order to have .registerKotlinModule()
, you need to have this dependency
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.18.2")
It should function the same regardless of whether the input is a String
or a ByteArray
.