Sunday, 10 July 2016

Episode 2 - Messaging with GRAILS

JMS (Java Messaging Service) is always a much orated topic, because of its applicability, expediency, and implementation in diverse plots.

I thought of exploring JMS again ,but after adding a different flavour to it. Confused Hmmmm!!!!

The flavour is of Spring and Grails 3 i.e. using Spring JMS in Grails framework.

Spring really has made JMS easy to implement.

I have Queues and Topics using APACHE ACTIVE MQ 5.13.3.

The source code is available at GITHUB

The Objective being very simple:

1) A message will be sent to a Queue/Topic (Using JMSTemplate).

2) A Listener implementation listening to particular destinations. [Please note: Since the intention was to receive messages asynchronously so we have tried with Listener here rather than receiving it through JMS Template ]

    a) Listener implementation is done using following ways:

        Registered bean in the Spring Applicaion Context using Message Listener Adapter.
        Registered bean in the Spring Applicaion Context by implementing MessageListener interface.
        Annotating registered beans in the application context.
    Will discussing each of the implementations configuration wise.

3) Applying Message Converters in order to transfrom Messages To/From custom types.
4) Integrating Message Validators with the Listener.

Will be discussing each of the implementations configuration wise along with some custom configuration for more added flexibility to the whole framework.

Grails does provide a jms plugin and that is really cool.
With a registered bean (using static exposes = ['jms'] in the Bean class) in the application context we can annotate a method with @Queue/@Subscriber specifying the destination name within the annotation like @Subscriber(topic = "topic.name") and @Queue(name='queue.name') and that method starts listening to that destination.

However for sending messages, Grails JMS plugin includes a bean jmsService. We can use the bean to send messages like the following:


def jmsService


jmsService.send(queue:"mic1.queue","First Message")
jmsService.send(topic:"mic.topic","Broadcast Message")


So using named propperty (queue/topic) we can specify the destination. That's flexible!!!

However in the documentation of the plugin custom configuration options are there, but I personally found it difficult to configure them in Grails 3.

So I resort to Spring JMS.

Lets get back to action:

Added following dependencies in build.gradle


compile "org.springframework:spring-jms:4.2.0.RELEASE"
compile "org.apache.activemq:activemq-core:5.7.0"

For sending messages to the destination:

 jmsTemplate.convertAndSend "mic1.queue","FirstMessage With Template"
 jmsTemplate.convertAndSend "mic2.queue","FirstMessage With Template For Annotated Listener"
jmsTemplate is configured in resources.groovy as:


 jmsConnectionFactory(ActiveMQConnectionFactory) {
        brokerURL = 'tcp://localhost:61616'
    }
 

 customMessageConverter2(CustomMessageConverter2)

    jmsTemplate(JmsTemplate) {
        connectionFactory = jmsConnectionFactory
        messageConverter = customMessageConverter2
    }

jmsConnectionFactory makes establishes connection with the broker and customMessageConverter2 is used for Message transformation as siad before. both the beans are used in configuring jmsTemplate.

Grails automatically injects the bean of the same type when we decalare a bean with the same name as in configuration.

So in while declaring:


JmsTemplate jmsTemplate

in the controller, we have not used any @Autowired annotation. Grails does that auto injection, as Grails follows CoC (Convention over Configuration) principle. Cool isn't it.

Now lets go to Listener section:

Here we have implemented Message Listener with the help of MessageListenerAdapter, and has also mentioned the default listener method, which will handle message processing.

We then need to register this Listner with the Listener Container Factory specifying the destination and the transaction manager.

As:

 messageListener(MessageListenerAdapter, ref("messageDelegateService")) {
        defaultListenerMethod = "receive"
    }
 
 
   jmsContainerQueue(DefaultMessageListenerContainer) {
        connectionFactory = jmsConnectionFactory
        destinationName = "mic1.queue"
        messageListener = messageListener//ref("messageConsumerJMSService")
        transactionManager = transactionManager
        //autoStartup = false
    }


The bean i.e. messageDelegateService, that we have used here implements an interface. We can also register a any class which do not implement interface.

As:

 messageListenerTopic(MessageListenerAdapter, ref("messageConsumerService")) {
        defaultListenerMethod = "interceptMessage3"
    }
 
 jmsContainerTopic2(DefaultMessageListenerContainer) {
        connectionFactory = jmsConnectionFactory
        destinationName = "mic.topic"
        messageListener = messageListenerTopic//ref("messageConsumerJMSService")
        transactionManager = transactionManager
        //autoStartup = false
    }

This part is committed in my code base as I have not implemented topic. The source code can be look up at GITHUB

Next we have implemented an annotated Listener.
For this annotated listener, I have defined a separate Java based configuration apart from resources.groovy and defined all the beans there.
The class has been named as AMQPConfiguration.

We have injected jmsConnectionFactory, which is the bean as defined in resources.groovy , and is needed for creating MessageListenerContainerFactory.
Ok lets come to it step by step.

We have a Listener class named AMQPMessageListener. We have annotated its method with @JmsListener by specifying the destination it will listen to and also the conainerFactory, that we have configured in the previous step. We can define multiple methods and annotate each method with a separate destinate that it will listen to.

Now in order to tell Spring that this is the Listener class, we have defined a bean of this class in the Java based configuration AMQPConfiguration and annotated the configuration class with the @EnableJMS, this annotation scans the beans defined in this context for Listener registration by looking up for methods annotated with @JmsListener.

The configuration looks like:

@Configuration
@EnableJms
public class AMQPConfiguration implements JmsListenerConfigurer {

    @Autowired
    ActiveMQConnectionFactory jmsConnectionFactory

 .........
 
 @Bean
    public AMQPMessageListener amqpMessageListener() {
        return new AMQPMessageListener()
    }
 
 .........
 
 @Bean
    public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
        DefaultJmsListenerContainerFactory factory =
                new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(jmsConnectionFactory);
        //factory.setDestinationResolver(destinationResolver());
        factory.setConcurrency("3-10");
        return factory;
    }
 
 .............
 }

Now why we have implemented JmsListenerConfigurer in the configuration class, I will get back to it.
So @EnableJMS also created JMSListener Container and from the jmsListenerContainerFactory bean that we have defined and bridge the destination and the listener.

The imeplentation of JmsListenerConfigurer provides more control to the whole setup because it helps us override the method configureJmsListeners(), which takes JmsListenerEndpointRegistrar as a parameter.

JmsListenerEndpointRegistrar is used for registration of JmsListenerEndpointRegistry, with the help of which we can define programmatically endpoint/listener. Here we have not implemented JmsListenerEndpointRegistry. We have used JmsListenerEndpointRegistrar to register containerFactory along with messaheHandlerMethodFactory, which the contains the MessageValidators and the MessageConverters at the Listener end.

View Subhankar Paul's profile on LinkedIn

Episode 1- Booting GRAILS with GRETTY

Since my last blog on Grails, I have been trying to start to quick deploy my app in jetty, while using run-app command, which by default uses tomcat 7 container.

However by preparing war with gradle and deploying it in jetty 8.1.17 externally is a success, but for quick and easy deployment I am keen on implementing run-app with jetty.

I changed the required runtime dependencies in build.gradle, started my app, in the command prompt I can see my app got deployed, but I was not able to access it. I tried by using different versions jetty server but with no success.

After a bit of searching I came to know about GRETTY plugin. Its configuration properties and good documentation helped me a lot and I was able to deploy my app with a single go using jetty 9 with appStart tasks. So thanks to Gretty!!!

The required configuration can be found at build.gradle at Here

Please Find my codebase at GitHub. Even I can pass the environment for which I want to build just like we pass while using grails run-app command.

Here we use:

gradle -Penv=<<env_name>> appStart

Now the env variable is then captured in the gretty task and is made available as JVM parameter. As:

gretty {
    // supported values:
    // 'jetty7', 'jetty8', 'jetty9', 'tomcat7', 'tomcat8'
  port = 8888
    servletContainer = 'jetty9'
    jvmArgs = ["-Dgrails.env=$env"]

    /**
     * This jvmArg is used to set config location
     * where Spring boot will look for Config Files
     */
    // '-Dspring.config.location=classpath:/config/'
}

suppose if we use -Penv=dev, then development environment related configuration properties are loaded from application.yml.
For the sake of clarity, I have defined two application.properties in the src/main/resources folder as application-development.yml and another as application-staging.yml

when we use -Penv=dev along with development environment related configuration from application.yml, properties from application-development.yml are alsoe being loaded. That's Grails speciality

Now if we use -Penv=staging, along with staging environment related configuration from application.yml (if any, since it is custom environment that I have defined, there will be no block for staging in application.yml when we create a Grails application using create-app) properties from staging-development.yml are alsoe being loaded.

Properties access code from both the yml files, is there in Bootstrap.groovy, so see the whole thing in operation.

I have tried explore Spring JMS with Grails.

Here are the DETAILS
View Subhankar Paul's profile on LinkedIn

Some Steps with GRAILS




Learning Grails, makes me more inquisitive. Makes me explore its different facets with lots of excitement.
Moreover its similarity with Spring and the CoC feature makes me walk a lot more with Grails!!!

The idea behind the startup pic is to devote this whole session in exploring and understanding more about the Grails 3 Features

So Let's start

View Subhankar Paul's profile on LinkedIn