first project Page History


First Project Example

The idea of this project is to build a basic processor (it will take queries and process them) and a client.

Prerequisites

You will need:

  • Basic knowledge of Java.
  • A Rabbit MQ up and running on localhost.
  • Java 1.7 installed.
  • Eclipse or whatever you feel comfortable.
  • Maven 3.X

Configuration of the project

To start coding you only need to create a new maven project. By default we want to compile against Java 1.7 or upper, so we just tell to maven:

    <build>
        <finalName>${project.artifactId}-${project.version}</finalName>
        <directory>target</directory>
        <outputDirectory>target/classes</outputDirectory>
        <sourceDirectory>src/main/java</sourceDirectory>
        <testSourceDirectory>src/test/java</testSourceDirectory>
        <testOutputDirectory>target/test-classes</testOutputDirectory>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
        <filters>
        </filters>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

Once this is done we must include dependencies for this project.

Level2 MQ framework is just heading to support several types of MQ queues but today we only support rabbit so go ahead and add the dependency on this implementation.

    <dependencies>
        <dependency>
            <groupId>com.level2.server.mq</groupId>
            <artifactId>level2-rabbit-mq-impl</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

With this in place you are ready to program your first micro service.

Let's create a simple interface for our first class.

package com.level2.enterprise.nebula.mq.example;

public interface MyFistMQService extends RabbitProcessingNode {
    public String helloWorld(String name);
}

And we need to implement this interface. Since we want it to be an autonomous microservice we will want to extend it from the class AnnotatedRabbitMQProcessor. It will take charge of initialize the queues, connect to the server and leave everything ready to be processed.

If you do this you will end with something similar to this.

package com.level2.enterprise.nebula.mq.example;

import com.level2.enterprise.nebula.mq.api.ExchangeDescriptor;
import com.level2.enterprise.nebula.mq.processor.AnnotatedRabbitMQProcessor;

public class MyFistMQServiceImpl extends AnnotatedRabbitMQProcessor implements MyFistMQService  {

    public MyFistMQServiceImpl(ExchangeDescriptor exchange) {
        super(exchange);
    }

    @Override
    public String helloWorld(String name) {
        // TODO Auto-generated method stub
        return null;
    }

}

And this class does nothing. So let's tell our system that we want this method to be connected to the RabbitMQ server and keep it waiting for messages. Also we want to implement our method so it responds with a nice message when called.

The first is done with an annotation @QueuedMethod. It requires a parameter telling server where to find it.

    @Override
        @QueuedMethod(queueName="com.level2.mq.queue.test.hello")
    public String helloWorld(String name) {
        // TODO Auto-generated method stub
        return null;
    }

And we can implement it also to return a nice message. If we receive your name we will want to tell you hello.

    @Override
    @QueuedMethod(queueName="com.level2.mq.queue.test.hello")
    public String helloWorld(String name) {
        return String.format("Hello %s, we are pleased to have you here...", name);
    }

And that's all. Every time someone send a message to the exchange of the constructor (more on this later) and specifies as topic com.level2.enterprise.nebula.mq.example.MyFistMQServiceImpl.helloWorld (helloWorld) it will arrive to that method and the response to the customer.

Bootstrapping the example

The only thing missing is to build the exchange descriptor for our project and a Main class that can be called from command line.

The exchange descriptor tells the clients where to route their messages, it will then take the routing parameter inside the message and redirect the message to the correct queue.

Is very simple, and we implement it as an enum.

package com.level2.enterprise.nebula.mq.example;

import com.level2.enterprise.nebula.mq.api.ExchangeDescriptor;

public enum ExampleExchangeDescriptor  implements ExchangeDescriptor {
    RABBIT_DEFAULT_EXCHANGE("com.level2.mq.example");

    private final String exchangeHandle;

    private ExampleExchangeDescriptor(final String exchangeHandle) {
        this.exchangeHandle = exchangeHandle;
    }

    @Override
    public String toString() {
        return exchangeHandle;
    }
}

The Main class is also rather simple. Just creates a new instance of our class using the exchange descriptor waits 10 seconds and stops everything.

package com.level2.enterprise.nebula.mq.example;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static Logger staticLog = LoggerFactory.getLogger(Main.class);

    private Logger log = LoggerFactory.getLogger(Main.class);

    MyFistMQService service;

    public Main() {
        service = null;
    }

    public void startProcessor() {
        log.info("Starting the processor, our implementation...");
         service = new MyFistMQServiceImpl(ExampleExchangeDescriptor.RABBIT_DEFAULT_EXCHANGE);
    }
    public void stopProcessor() {
        log.info("Stopping the processor.");
         service.shutdown();
    }

    public static void main(String[] args) {
        staticLog.info("Starting...");
        Main main = new Main();
        main.startProcessor();
        staticLog.info("Waiting 10 seconds");
        try {
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        main.stopProcessor();
        staticLog.info("Finished!");

    }

}

The log shown by the application is very descriptive.

00:15:54,128  INFO com.level2.enterprise.nebula.mq.example.Main - Starting...
00:15:54,128  INFO com.level2.enterprise.nebula.mq.example.Main - Starting the processor, our implementation...
00:15:54,234  INFO com.level2.enterprise.nebula.mq.processor.AnnotatedRabbitMQProcessor - Creating processor MQ for method class com.level2.enterprise.nebula.mq.example.MyFistMQServiceImpl.helloWorld
00:15:54,234  INFO com.level2.enterprise.nebula.mq.processor.AnnotatedRabbitMQProcessor - We are connecting method class com.level2.enterprise.nebula.mq.example.MyFistMQServiceImpl.helloWorld to queue com.level2.mq.queue.test.hello
00:15:54,239  INFO com.level2.enterprise.nebula.mq.example.Main - Waiting 10 seconds
00:15:54,239  INFO com.level2.enterprise.nebula.mq.processor.threaded.RabbitThreadProcessor - Thread processor is trying to connect to queue com.level2.mq.queue.test.hello
00:15:54,266  INFO com.level2.enterprise.nebula.mq.processor.AbstractRabbitMQManager - Connecting to server localhost on port 5672
00:15:54,405  INFO com.level2.enterprise.nebula.mq.processor.AbstractRabbitMQManager - Initialize exchange [com.level2.mq.example]
00:15:54,408  INFO com.level2.enterprise.nebula.mq.processor.AbstractRabbitMQManager - Initialize queue [com.level2.mq.queue.test.hello]
00:15:54,410  INFO com.level2.enterprise.nebula.mq.processor.AnnotatedRabbitMQProcessor - We are binding queue com.level2.mq.queue.test.hello of exchange com.level2.mq.example to method class com.level2.enterprise.nebula.mq.example.MyFistMQServiceImpl.helloWorld
00:15:54,413  INFO com.level2.enterprise.nebula.mq.processor.threaded.RabbitThreadProcessor - Running this tread for channel 1
00:16:04,240  INFO com.level2.enterprise.nebula.mq.example.Main - Stopping the processor.
00:16:04,420  INFO com.level2.enterprise.nebula.mq.processor.threaded.RabbitThreadProcessor - Thread processor is trying to connect to queue com.level2.mq.queue.test.hello
00:16:04,526  INFO com.level2.enterprise.nebula.mq.example.Main - Finished!

Now you should use this same library to create a client. But as you seen is very easy to work with it.


Last edited by Gonzalo Aguilar Delgado