views:

203

answers:

2

Hi there,

I am trying to implement jms to my grails application.

I have several JMS consumer in a spring based enviroment listining on an ActiveMQ broker. I wrote a simple test commandline client which creates messages and receives them in an request response manner.

Here is the snippet that sends a MapMessage in Spring JMS way. This works for me as long I am in my spring world.

final String corrID = UUID.randomUUID().toString();
asyncJmsTemplate.send("test.RequestQ", new MessageCreator() 
{
 public Message createMessage(Session session) throws JMSException {
  try {
   MapMessage msg = session.createMapMessage();
   msg.setStringProperty("json", mapper.writeValueAsString(List<of some objects>));     
   msg.setJMSCorrelationID(corrID);
   msg.setJMSReplyTo(session.createQueue("test.ReplyQ"));
   return msg;
  } catch (JsonGenerationException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (JsonMappingException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return null;
 }
});

BUT when I tried to implement this methods to my grails test app I receive some METHOD_DEF exceptions. Sending simple TextMessages via the jmsTemplate.convertAndSende(Queue, Message) provided by the JMS Plugin works.

Can any one help me? Is this a common problem?

Cheers Hans

A: 

Not actually trying this out, I have to believe this is a syntax problem. What you're really doing with that anonymous class is passing a closure containing all the MessageCreator code into the constructor for the MessageCreator class. In Groovy, closures can be passed as the last argument to a function merely by placing it after the function name or the parenthesized first arguments.

SomeFunction( arg1, arg2) { some code }

is the same as

SomeFunction( arg1, arg2, { some code } )

What you really want is to convert the closure into an anonymous instance of a MessageCreator, which I believe you can accomplish by:

asyncJmsTemplate.send("test.RequestQ", 
          { code in the anonymous block } as MessageCreator );

I found this on StackOverflow, actually, though it's a poorly created question. Read all the responses, and you should see something relevant: http://stackoverflow.com/questions/758700/best-groovy-closure-idiom-replacing-java-inner-classes

Bill James
A: 

Hi Hans,

I have had the same problems and here is my working solution: I have created a new class MyMessageCreator in the src folder which implements the origin JMS MessageCreator interface.

With this I can create a new MyMessageCreator object and can call the createMessage(Session session) function to generate a new message.

To get the session object I use the jmsTemplate.

public class MyMessageCreator implements MessageCreator {

    @Override
    public Message createMessage(Session session) throws JMSException {
        return session.createMapMessage();
    }

}

Here is the relevant groovy code:

Session session = jmsTemplate.getConnectionFactory().createConnection().createSession(false, Session.AUTO_ACKNOWLEDGE)
MapMessage msg = new MyMessageCreator().createMessage(session);

Hope this helps, Mirko

Mirko