1

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

enter image description 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

Update

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...

enter image description here

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"}

11
  • What is you object mapper? Do you have ObjectMapper().registerKotlinModule()? if it is an issue, I could formulate it as an answer Commented Feb 1 at 12:49
  • I tried to use ObjectMapper() without .registerKotlinModule(). So I guess, it is a case. So I will add an answer Commented Feb 1 at 13:17
  • Also FTR this is on windows as well so the encoding may be wonky. Like Spring may be expecting linux or something but it seems to parse fine in the binary so :shrug: Commented Feb 1 at 15:26
  • Could you attach the message you send using postman for reproducing simplicity? Commented Feb 1 at 16:25
  • I tried to use postman as show in the link that you have provided and the message was deserialized correctly Commented Feb 1 at 16:36

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

5 Comments

To start with I had the dep, and I will test that with the debug case. I will update the question title to make it more clear but even if that helps the debug case how do I get the fun greeting(message: TestMessage): Greeting { case to work.
Sorry this didn't help I will update the question to show that I tried this approach and it failed. Thanks for trying though.
I do think you may be on to something with the escapes though I know it isn't using those let me take it to our AI overloards
NM even when I force escape it it just makes it worse com.fasterxml.jackson.core.JsonParseException: Unexpected character ('\' (code 92)): was expecting double-quote to start field name at [Source: REDACTED (StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION disabled); line: 1, column: 2]
Once I register with @Bean fun objectMapper() = ObjectMapper().registerKotlinModule() I should be able to use injection instead of declaring correct so we can remove the line val objectMapper = ObjectMapper().registerKotlinModule() and show how to inject it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.