You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by MarkD <ma...@googlemail.com> on 2012/03/11 12:17:22 UTC

MessageFormatException using requestBody InOut over activemq JMS

Hi all,

I have a pojo that returns a Map of Custom objects. In my camel context this
pojo is wired to receive requests from a jms (activemq) queue, i.e., it can
act as a simple service. Code below:

@Override
public Map<String, ParameterGroup> getParameterGroups() {
    return model.getParameterGroups();
}

I have a client which is a pojo producer (template injected using @Produce).
It invokes the service using the template.requestBody(Object) method. Code
below:

@Produce(uri = "activemq:requestParameterGroups")
ProducerTemplate requestParameterGroupsProducerTemplate;

@Override
public List<ParameterGroup> requestParameterGroups() {
    // testing service call
    List<ParameterGroup> parameterGroups = new ArrayList<ParameterGroup>();
    parameterGroups = (List<ParameterGroup>)
requestParameterGroupsProducerTemplate.requestBody(null);
    System.out.println("Received " + parameterGroups.size() + " parameter
groups.");
    return parameterGroups;
}

I have a question and an error. First the error:

The request makes it to the pojo service bean which attempts to return the
Map of custom objects but the return message times out. Looking at the logs
I can see a Camel runtime exception wrapping a spring jms
MessageFormatException which claims "Only objectified primitive objects,
String, Map, and List types are allowed but was...it then lists the entire
value part of the returned Map (Note, it does not print out the key)


On a side note: I assume the requestBody parameter Object can be null if you
don't need to send any parameters to the request, i.e., if the service
simply acts like a getter as in the case above.

Looks like the error is an activemq message. I can't find much info on it
other than it seems to occur when people attempt to put Objects in the
Header.

Thanks!

--
View this message in context: http://camel.465427.n5.nabble.com/MessageFormatException-using-requestBody-InOut-over-activemq-JMS-tp5554469p5554469.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: MessageFormatException using requestBody InOut over activemq JMS

Posted by bjpeter <bj...@hawaii.edu>.
Aloha,

I recently got the same exception as MarkD did.  I'm using Camel version
2.9.0. Attached is my source code for some tests. The first three test cases
pass, but the fourth one fails.

Is there a fix for this issue?  I'd like to put a map containing any
serializable object into the body without having to wrap the map in some
serializable object. The latter works, but I'd much prefer just using the
map.

Thanks!
BJ

**************************************************

package com.test;

import java.io.Serializable;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import org.apache.activemq.camel.component.ActiveMQComponent;
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.log4j.Appender;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;

/**
 * This program puts four different objects in the body of a Camel message.
If
 * the object is a map that contains an object that is not an objectified
 * primitive (e.g. not an Integer), an exception is thrown.
 * 
 * @author BJ Peter DeLaCruz <bj...@hawaii.edu>
 */
public class TestCamelJmsWithMap {

  private static final Logger LOGGER =
Logger.getLogger(TestCamelJmsWithMap.class);

  private static final String DIRECT_URL = "direct:start";
  private static final String QUEUE_URL = "activemq:queue:myqueue";

  /**
   * This program runs four different test cases, which are:<br>
   * <br>
   * <ol>
   * <li>A serialized object called TestObject.</li>
   * <li>A map of primitive types.</li>
   * <li>An object that wraps a map of TestObjects.</li>
   * <li>A map of TestObjects.</li>
   * </ol>
   * The first three test cases pass, but the last one fails.<br>
   * <br>
   * 
   * @param args None.
   * @throws Exception If there are problems.
   */
  public static void main(String... args) throws Exception {
    // test(new TestObjectBodyFactory()); // This test case works.
    // test(new PrimitiveMapBodyFactory()); // This test case works.
    // test(new WrappedObjectBodyFactory()); // This test case works.
    test(new TestObjectMapBodyFactory()); // This test case fails!
  }

  /**
   * Sends an object in the body of a Camel message.
   * 
   * @param bodyFactory The factory for creating the object to be used in
the
   * body.
   * @throws Exception If there are problems.
   */
  public static void test(BodyFactory bodyFactory) throws Exception {
    Logger logger = Logger.getRootLogger();
    for (Enumeration<?> appenders = logger.getAllAppenders();
appenders.hasMoreElements();) {
      Appender appender = (Appender) appenders.nextElement();
      if (appender instanceof ConsoleAppender) {
        logger.removeAppender(appender);
      }
    }
    ConsoleAppender console = new ConsoleAppender(new PatternLayout("%d [%t]
%-5p %c - %m%n"),
        "System.out");
    logger.addAppender(console);
    logger.setLevel(Level.INFO);

    final CamelContext context = new DefaultCamelContext();
    context.addComponent("activemq",
       
ActiveMQComponent.activeMQComponent("vm://localhost?broker.persistent=false"));

    context.addRoutes(new RouteBuilder() {
      public void configure() throws Exception {
        from(DIRECT_URL).to(QUEUE_URL);
        from(QUEUE_URL).log("received message: ${body}");
      }
    });
    context.start();

    ProducerTemplate producerTemplate = context.createProducerTemplate();
    while (true) {
      try {
        producerTemplate.sendBody(DIRECT_URL, bodyFactory.createBody());
      }
      catch (Exception e) {
        LOGGER.error("", e);
      }
      Thread.sleep(1000L);
    }
  }

  /** A factory for creating objects to be used in test cases. */
  public static interface BodyFactory {
    /** Creates the object used in the body of a Camel message. */
    public Object createBody();
  }

  /** A factory for creating a map of primitives. */
  static class PrimitiveMapBodyFactory implements BodyFactory {
    /** {@inheritDoc} */
    @Override
    public Object createBody() {
      Map<Integer, Integer> map = new HashMap<Integer, Integer>();
      map.put(1, 2);
      return map;
    }
  }

  /** A factory for creating a TestObject. */
  static class TestObjectBodyFactory implements BodyFactory {
    /** {@inheritDoc} */
    @Override
    public Object createBody() {
      return new TestObject();
    }
  }

  /** A factory for creating a map of TestObjects. */
  static class TestObjectMapBodyFactory implements BodyFactory {
    /** {@inheritDoc} */
    @Override
    public Object createBody() {
      Map<Integer, TestObject> map = new HashMap<Integer, TestObject>();
      map.put(1, new TestObject());
      return map;
    }
  }

  /** A factory for creating an object that contains a map. */
  static class WrappedObjectBodyFactory implements BodyFactory {
    /** {@inheritDoc} */
    @Override
    public Object createBody() {
      Map<Integer, TestObject> map = new HashMap<Integer, TestObject>();
      map.put(1, new TestObject());
      return new Wrapper(map);
    }
  }

  /** The test object. */
  static class TestObject implements Serializable {
    /** {@inheritDoc} */
    @Override
    public String toString() {
      return "This is a test.";
    }
  }

  /** A wrapper that wraps an object. */
  static class Wrapper implements Serializable {

    private Object contents;

    /**
     * Creates a new Wrapper.
     * @param contents The object to wrap.
     */
    public Wrapper(Object contents) {
      this.contents = contents;
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
      return this.contents.toString();
    }

  }

}


--
View this message in context: http://camel.465427.n5.nabble.com/MessageFormatException-using-requestBody-InOut-over-activemq-JMS-tp5554469p5711703.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: MessageFormatException using requestBody InOut over activemq JMS

Posted by MarkD <ma...@googlemail.com>.
Sorry:

Changing the server to return a List instead solved the problem.

Should read:

Changing the *service* to return a List instead solved the problem.

i.e.
@Override
public List<ParameterGroup> getParameterGroups() {
   return model.getParameterGroupsAsList();
}

--
View this message in context: http://camel.465427.n5.nabble.com/MessageFormatException-using-requestBody-InOut-over-activemq-JMS-tp5554469p5555754.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: MessageFormatException using requestBody InOut over activemq JMS

Posted by MarkD <ma...@googlemail.com>.
Ok, I looked into this and found the message in the Activemq source. It looks
like it is trying to set an Object Property using the values part of the
return map. Maybe something it getting confused somewhere.

Changing the server to return a List instead solved the problem. Not sure
why!

--
View this message in context: http://camel.465427.n5.nabble.com/MessageFormatException-using-requestBody-InOut-over-activemq-JMS-tp5554469p5555747.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: MessageFormatException using requestBody InOut over activemq JMS

Posted by MarkD <ma...@googlemail.com>.
For what it is worth, i've just noticed the incorrect return type on the
invoker. Obviously that's not the cause of the error.

@Override 
public List<ParameterGroup> requestParameterGroups() { 
    // testing service call 
    List<ParameterGroup> parameterGroups = new ArrayList<ParameterGroup>(); 
    parameterGroups = (List<ParameterGroup>)
requestParameterGroupsProducerTemplate.requestBody(null); 
    System.out.println("Received " + parameterGroups.size() + " parameter
groups."); 
    return parameterGroups; 
}

should be

@Override
	public Map<String, ParameterGroup> requestParameterGroups() {
		Map<String, ParameterGroup> parameterGroups = new HashMap<String,
ParameterGroup>();
		parameterGroups = (Map<String, ParameterGroup>)
requestParameterGroupsProducerTemplate.requestBody(null);
		System.out.println("Received " + parameterGroups.size() + " parameter
groups.");

		return parameterGroups;
	}

--
View this message in context: http://camel.465427.n5.nabble.com/MessageFormatException-using-requestBody-InOut-over-activemq-JMS-tp5554469p5554786.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: MessageFormatException using requestBody InOut over activemq JMS

Posted by MarkD <ma...@googlemail.com>.
Looking at this closer, it seems to suggest I cannot return/send a custom
objects, only String, Map, List and objectified primitives.

--
View this message in context: http://camel.465427.n5.nabble.com/MessageFormatException-using-requestBody-InOut-over-activemq-JMS-tp5554469p5554519.html
Sent from the Camel - Users mailing list archive at Nabble.com.