Have you used the WSO2 MB with AMQP? If not this will help you get started on AMPQ with WSO2 MB. I am using the newly released WSO2MB 3.0.0-Alpha4 and RabbitMQ AMQP Java client in this example.

Setting up the project

For this example, I created a Maven project. Following code correspond to the pom.xml used in the project

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>io.github.a5anka.amqp.helloworld</groupId>
    <artifactId>pub-sub</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>3.3.1</version>
        </dependency>
    </dependencies>
    
</project>

I have added RabbitMQ AMQP client as a dependency in the pom.xml file.

Publisher

Publisher class connect to the WSO2 MB and publish a simple text message to the message queue “hello”.

package io.github.a5anka.amqp.helloworld;

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;

public class Publisher {

    private final static String QUEUE_NAME = "hello";

    public static void main(String[] argv)
            throws java.io.IOException, InterruptedException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("admin");
        factory.setPassword("admin");
        Connection connection = factory.newConnection();

        Channel channel = connection.createChannel();

        channel.queueDeclare(QUEUE_NAME, true, false, false, null);

        String message = "Hello world!!";
        channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
        System.out.println(" [x] Sent '" + message + "'");

        channel.close();
        connection.close();

    }
}

Subscriber - Synchronous

Subscriber code specified below will connect to the WSO2 MB and retrieve the message published in “hello” message queue and print it in the console.

package io.github.a5anka.amqp.helloworld;

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.QueueingConsumer;

public class Subscriber {

    private final static String QUEUE_NAME = "hello";

    public static void main(String[] argv)
            throws java.io.IOException,
            java.lang.InterruptedException {

        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("admin");
        factory.setPassword("admin");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.queueDeclare(QUEUE_NAME, true, false, false, null);
        channel.queueBind(QUEUE_NAME, "amq.direct", QUEUE_NAME);
        System.out.println(" [*] Waiting for messages.");

        QueueingConsumer consumer = new QueueingConsumer(channel);
        channel.basicConsume(QUEUE_NAME, false, consumer);

        while (true) {
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
            String message = new String(delivery.getBody());
            System.out.println(" [x] Received '" + message + "'");

            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
        }
    }
}

Subscriber - Asynchronous

Following Subscription implementation receives messages asynchronously.

package io.github.a5anka.amqp.helloworld;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class AsyncSubscriber {

    private final static String QUEUE_NAME = "hello";

    public static void main(String[] argv)
            throws java.io.IOException,
            java.lang.InterruptedException {

        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("admin");
        factory.setPassword("admin");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.queueDeclare(QUEUE_NAME, true, false, false, null);
        channel.queueBind(QUEUE_NAME, "amq.direct", QUEUE_NAME);
        System.out.println(" [*] Waiting for messages.");

        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                                       AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println(" [x] Received '" + message + "'");

                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        };
        channel.basicConsume(QUEUE_NAME, false, consumer);

    }
}

Running the example

I assume you have installed the WSO2 MB in your machine and it is run using the default configuration. You can first run the publisher code. This will publish a message in to the “hello” queue. Then you can use subscriber code to retrieve and print the message in the message queue.

IBM WebSphere MQ Explorer

This post include a summary on IBM WebSphere MQ Queue Managers, Queues and Channels. Knowing these concepts will help you to do simple tasks like creating a queue, sending and receiving messages from a queue.

Queue Managers

Queue manager is the top level object that holds in the network (Such as queues and channels). The main tasks done through a queue manager are,

  • Start channels
  • Process MQI calls
  • Create, delete, alter queues and channel definitions
  • Run a command server to process MQSC commands

See IBM Documentation for more details.

Queues

Queue holds the messages destined to it and send the messages to consumers in the receiving order. A queue has two defined limits.

  • Maximum number of messages that it can hold
  • Maximum length of a message.

There are several queue types that can be used with the IBM MQ. They are,

  • Local queue
  • Transmission queue
  • Remote queue definition
  • Alias queue
  • Model queue
  • Cluster queue
  • Shared queue
  • Group definition queue

See IBM Documentation for more details.

Channels

Channels are used to send and receive messages to and from a queue.

MQI Channel

Client applications use these channel to send and receive messages.

  • Server connection - This is the server end of the channel
  • Client connection

Message channel

These are used to link two queue managers

See IBM Documentation for more details.

WSO2 GREG uses RXT files to describe the data model of an artifact. There are mainly two steps in creating an artifact using RXT files.

  1. Creating the RXT file. You can find details about the syntax used in RXT files in here.
  2. Deploying created RXT file in GREG. This is described in detail in here.

Relationship Model

Following is an explanation about the relationship model used in the GREG’s RXT files. In RXT files, we use the “relationships element” (more details here) to define relationships between two artificats. You can find several RXT examples inside

1
$GREG_HOME/samples/asset- models
directory. Following is an extract from the sample file
1
$GREG_HOME/samples/asset-models/TestPlanModel/registry-extensions/TestSuite.rxt
.

1
2
3
4
<relationships>
  <association type="usedBy" source="@{testCases_entry:value}"/>
  <dependency type="depends" target="@{testCases_entry:value}"/>
</relationships>

Here in line 2, we have added a “usedBy” association in the TestCase artifact to the TestSuite artifact using the association element. Note that we have used source attribute to indicate that the relationship is from “TestCase” to “TestSuite”. In the line 3 we have added a dependency in the TestSuite on “TestCase”. Note that we have used the “target” attribute to indicate that the relationship is from “TestSuite” to “TestCase”. The relationships element only indicate the type of relationship. To make it relate to one or many, we can use different type of fields. You can find a description about available field types from here.

If we look at the same sample file we took earlier we can see that a “TestSuite” artifact have an association with many “TestCase” artifacts. The relevant RXT code is mentioned below.

1
2
3
4
5
6
7
8
9
10
11
12
<table name="TestCases">
  <subheading>
    <heading>Type</heading>
    <heading>Path</heading>
  </subheading>
  <field type="option-text" maxoccurs="unbounded" path="true">
    <name>Case</name>
    <values>
      <value>Test Case</value>
    </values>
  </field>
</table>

In line 6 we have defined the field type as “option-text” with attribute “maxoccurs” set to “unbounded”. Therefore we can add many TestCases for a Testsuite. If we have used a field of type text field then a TestSuite can have only one TestCase.

Similarly you can use different combination of the “relationships” elements and field elements to create different relationship patterns.

Examples

Some Examples are listed below, I am taking “Project group” and “Person” as artifcats for following examples. I have only shown the relevant parts of the RXT file. You have to add all other required elements to make it a valid RXT file.

One-to-one

<!-- In Person RXT definition -->
<relationships>
    <association type="groupOwnerOf" source="@{overview_group}"/>
    <association type="own" target="@{overview_group}"/>
</relationships>

<content>
    <table name="Overview">
        <field type="text" required="true" path="true">
            <name>Group</name>
        </field>
    </table>
</content>

Many-to-many

<!-- In Person RXT definition -->
<relationships>
    <association type="member" source="@{membership_entry:value}"/>
    <association type="memberOf" target="@{membership_entry:value}"/>
</relationships>

<content>
    <table name="Membership">
        <subheading>
            <heading>Type</heading>
            <heading>Path</heading>
        </subheading>
        <field type="option-text" maxoccurs="unbounded" path="true">
            <name>Member</name>
            <values>
                <value>Junior</value>
                <value>Senior</value>
            </values>
        </field>
    </table>
</content>

One-to-many

<!-- In ProjectGroup RXT -->
<relationships>
    <association type="member" target="@{members_entry:value}"/>
</relationships>

<content>
    <table name="Members">
        <subheading>
            <heading>Type</heading>
            <heading>Path</heading>
        </subheading>
        <field type="option-text" maxoccurs="unbounded" path="true">
            <name>Member</name>
            <values>
                <value>Junior</value>
                <value>Senior</value>
            </values>
        </field>
    </table>
</content>

Have you ever faced a situation where you wanted to execute a function you want instead of sending the form data when the form submit button is clicked. This post describes one way you can do just that. This behavior is very useful in tasks like form data validation. We don’t want to send form data to server if the data validation fails.

Code snippets

Assume your form has the following structure,

<form id="my-form">
  Name: <input type="text" name="name"><br />
  Age: <input type="text" name="age"><br />
  <button type="submit">Send</button>
</form>

You can override the default form submission behavior by using a JavaScript function like below for the form’s onsubmit event. Here the usage of “e.preventDefault()” function is important to avoid form data submission.

var form = document.getElementById('my-form');

// Send a message when the form is submitted.
form.onsubmit = function(e) {

  //Do something... 

  e.preventDefault();
};
Adding a Maven dependency to an Eclipse project

Managing dependencies is one of the important task in developing a complex Java project. This normally includes searching for depending libraries and adding them to the Eclipse project. Sometime this is not a very pleasant task. But the good news is, Maven make it easy to handle dependencies in Java projects.

I wrote an article on creating an Eclipse project using Maven previously. This article is a follow-up on that.

Searching for dependency

Imagine that you want to use a particular Java class in you project and you want to find and include the corresponding Java library in your project. You can use http://search.maven.org to search for a Maven dependency. They have an advanced search which is very helpful if you only know the name of the required class.

Adding the dependency to Maven

From the results you get from the search identify the required library. By clicking on a version number in the search results you can get the dependency information for a artifact. Following is an example of Maven dependency snippet.

<dependencies>
  <dependency>
    <groupId>org.apache.synapse</groupId>
    <artifactId>synapse-core</artifactId>
    <version>2.1.0</version>
  </dependency>
  <!-- Add more dependencies if required -->
</dependencies>

Updating the eclipse project

Add this dependency information to pom.xml (I assume you already have and pom.xml in your project directory. If not add a pom.xml or read this post to know about creating an Eclipse project using Maven) and run following command to update the eclipse project.

mvn eclipse:eclipse

Alternatively you can also use an Eclipse plugin to handle Maven dependencies. An example for such a plugin is the m2eclipse plugin.