PDA

View Full Version : sendMessage handles String but not Object



Slidewayz
Dec 31st, 2010, 01:56 AM
Hi,

I am very impressed with Spring-AMQP...thank you for the great work!!!

The build I'm using is the 12/27/10 snapshot.

I've run into a small problem. Sending text as a message works, but sending an object does not.

When I send a message using:



getRabbitTemplate().convertAndSend(routingKey, "text string");


handleMessage(String text) in my POJO works fine

However, when I change the convertAndSend and the POJO signature to an object:



getRabbitTemplate().convertAndSend(routingKey, myObject);

public void handleMessage(MyObject myObject)


I get this error:

SimpleMessageListenerContainer - Execution of Rabbit message listener failed, and no ErrorHandler has been set. <org.springframework.amqp.rabbit.listener.adapter.L istenerExecutionFailedException: Failed to invoke target method 'handleMessage' with argument type = [class [B], value = [{[B@7ab05cd7}]>org.springframework.amqp.rabbit.listener.adapter.L istenerExecutionFailedException: Failed to invoke target method 'handleMessage' with argument type = [class [B], value = [{[B@7ab05cd7}]

Please help with my newb question...thanks!!!

Dave Syer
Dec 31st, 2010, 02:33 AM
Thanks for the feedback.

Is MyObject Serializable? I think the default conversion falls back to Object.toString() if it can't serialize. If you need more control you can add a MessageConverter to your producer and consumer.

Slidewayz
Dec 31st, 2010, 03:27 AM
Thanks for the feedback.

Is MyObject Serializable? I think the default conversion falls back to Object.toString() if it can't serialize. If you need more control you can add a MessageConverter to your producer and consumer.

I subclassed MyObject to make it Serializable, but still can't get my POJO to accept it as MyObject. I have my RabbitTemplate set to use the JSON converter like the Stock example.

The Spring-AMQP Stock example appears to be passing Quote w/o it being serialized (RabbitMarketDataGateway, line 69)?

The Stock example's Client Handler handleMessage (line 47) has Quote as its signature.

I am essentially trying to do the same thing and AFAIK my code is the same since I based it on the Stock example.

Please let me know what I am missing.

Also, is there an example of how to implement MessageConverter? I don't know what MessageProperties to set/pass in.

Thanks again !!!

Dave Syer
Dec 31st, 2010, 06:12 AM
If you are using the JsonMessageConverter you don't need to implement Serializable, but your POJO and all its properties have to be convertible to JSON. I can see from your error message now that it is a JSON String, however it's not MyObject that is broken, but one of its properties of type B. Does that make sense? I'm not sure why the B is not convertible, but maybe we can work it out if you paste the source code.

Slidewayz
Dec 31st, 2010, 09:04 AM
Thank you once again, Dave.

The object I'm passing in is a value object. It has data types of string, int, boolean, date, and float. Along with that it has setters and getters and also hibernate stuff.

...I guess that is way too confusing for a json conversion!

I will create a simplified value object with only string & int properties and try that.

Slidewayz
Dec 31st, 2010, 03:50 PM
I've created a very simple value object that contains 1 string and 2 ints.

In the Spring-AMQP Stock example, I do not see any config of the JSON converter that I have not included (my messageListenerAdapter bean is identical).

When I pass this as an argument to convertAndSend, I still get the following error from Jackson. Why would I need to 'add/enable type information' when the Stock example does not? I am using jackson-all-1.6.4.jar and the 12/27 SNAPSHOT build of Spring-AMQP.


WARN] SimpleMessageListenerContainer - Execution of Rabbit message listener failed, and no ErrorHandler has been set. <org.springframework.amqp.support.converter.Message ConversionException: Failed to convert Message content>org.springframework.amqp.support.converter.Message ConversionException: Failed to convert Message content
at org.springframework.amqp.support.converter.JsonMes sageConverter.fromMessage(JsonMessageConverter.jav a:118)
at org.springframework.amqp.rabbit.listener.adapter.M essageListenerAdapter.extractMessage(MessageListen erAdapter.java:384)
at org.springframework.amqp.rabbit.listener.adapter.M essageListenerAdapter.onMessage(MessageListenerAda pter.java:332)
at org.springframework.amqp.rabbit.listener.AbstractM essageListenerContainer.doInvokeListener(AbstractM essageListenerContainer.java:280)
at org.springframework.amqp.rabbit.listener.AbstractM essageListenerContainer.invokeListener(AbstractMes sageListenerContainer.java:243)
at org.springframework.amqp.rabbit.listener.AbstractM essageListenerContainer.doExecuteListener(Abstract MessageListenerContainer.java:222)
at org.springframework.amqp.rabbit.listener.AbstractM essageListenerContainer.executeListener(AbstractMe ssageListenerContainer.java:192)
at org.springframework.amqp.rabbit.listener.SimpleMes sageListenerContainer$AsyncMessageProcessingConsum er.receiveAndExecute(SimpleMessageListenerContaine r.java:388)
at org.springframework.amqp.rabbit.listener.SimpleMes sageListenerContainer$AsyncMessageProcessingConsum er.run(SimpleMessageListenerContainer.java:307)
at java.lang.Thread.run(Thread.java:680)
Caused by: org.codehaus.jackson.map.JsonMappingException: No suitable constructor found for type [simple type, class rabbit.gateway.MyDataGateway$MyMockObject]: can not instantiate from JSON object (need to add/enable type information?)
at [Source: java.io.StringReader@54a50a00; line: 1, column: 2]
at org.codehaus.jackson.map.JsonMappingException.from (JsonMappingException.java:160)
at org.codehaus.jackson.map.deser.BeanDeserializer.de serializeFromObject(BeanDeserializer.java:478)
at org.codehaus.jackson.map.deser.BeanDeserializer.de serialize(BeanDeserializer.java:350)
at org.codehaus.jackson.map.ObjectMapper._readMapAndC lose(ObjectMapper.java:1980)
at org.codehaus.jackson.map.ObjectMapper.readValue(Ob jectMapper.java:1271)
at org.springframework.amqp.support.converter.JsonMes sageConverter.convertBytesToObject(JsonMessageConv erter.java:137)
at org.springframework.amqp.support.converter.JsonMes sageConverter.fromMessage(JsonMessageConverter.jav a:109)
... 9 more

Mark Fisher
Dec 31st, 2010, 03:54 PM
I would expect that if your object has no default constructor. Is that the case?

Slidewayz
Dec 31st, 2010, 04:27 PM
I would expect that if your object has no default constructor. Is that the case?

Funny you should ask that...I just added a public default empty constructor and a public constructor that sets all the properties from passed-in parms.

I still get the same error.

Slidewayz
Dec 31st, 2010, 05:00 PM
OK. I got it working by removing the MockObject that extends my class.

I think I now understand why the code in the AMQP-Stock example works (RabbitMarketDataGateway). Your MockStock is not what is sent in the message. I was sending my MockObject, so jackson didn't know how to type it.

Would I solve this problem by adding a default constructor for my MockObject inner class ?

Thank you all for your help !!!