Saturday, April 25, 2015

Email testing with Greenmail

When an application provides support for sending and receiving emails we need to be able to write test cases to automate the verification of this functionality. Green mail  is a great library for Implementing this functionality. Greenmail provide support for various mail protocols such as smtp, smtps, pop3 , pop3s , imap and imaps.

You can start a Greenmail server to listen with all these protocols enabled and listening on localhost with two lines of code.

        GreenMail greenMail = new GreenMail();
        greenMail.start();


When the server is started as above, the default ports of the above supported protocols are offset by 3000.

SMTP    : 3025    SMTPS  : 3465   POP3     : 3110   POP3S   : 3995  IMAP    : 3143  IMAPS  : 3993

However, if you start the server as above, more often than not, there will be a port conflict with some other program resulting in exceptions. Therefore you can configure the GreenMail server with the ServerSetup object with the protocol , binding address and port.

 ServerSetup setup = new ServerSetup(3025, "localhost", "smtp");
 GreenMail greenMail = new GreenMail(setup);

You can register a user to the server by using setUser method.

greenMail.setUser("user1@mail.com", "user1", "user1");

In order to receive mails from greenmail server object, waitForIncomingEmail method is available.

greenMail.waitForIncomingEmail(5000, 1);
Message[] messages = greenMail.getReceivedMessages();

In order to find more details, take a look at the source code at https://github.com/greenmail-mail-test/greenmail

Following is a sample on how to send a mail using java mail and receive it using greenmail with user authentication enabled.

import com.icegreen.greenmail.util.GreenMail;
import com.icegreen.greenmail.util.ServerSetup;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
import java.util.Properties;

public class GreenMailTest {

    public static void main(String[] args) throws InterruptedException, IOException, MessagingException {
        ServerSetup setup = new ServerSetup(3025, "localhost", "smtp");
        GreenMail greenMail = new GreenMail(setup);
        greenMail.setUser("user1@mail.com", "user1", "user1");
        greenMail.start();

        final String username = "user1";
        final String password = "user1";

        Properties props = new Properties();
        props.put("mail.smtp.auth", "true");
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.host", "localhost");
        props.put("mail.smtp.port", "3025");

        Session session = Session.getInstance(props,
                                              new javax.mail.Authenticator() {
                                                  protected PasswordAuthentication getPasswordAuthentication() {
                                                      return new PasswordAuthentication(username, password);
                                                  }
                                              });

        Message message = new MimeMessage(session);
        message.setSubject("Mail Subject");
        message.setText("Mail content");
        message.setFrom(new InternetAddress("user1@mail.com"));
        message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("user1@mail.com"));
        Transport.send(message);

        greenMail.waitForIncomingEmail(5000, 1);
        Message[] messages = greenMail.getReceivedMessages();
        System.out.println("Message length =>" + messages.length);
        System.out.println("Subject => " + messages[0].getSubject());
        System.out.println("Content => " + messages[0].getContent().toString());
        System.out.println("Done");
        greenMail.stop();
    }
}

Sunday, March 29, 2015

How to configure a ESB proxy service as a consumer to listen to two message broker queues

In this blog post, we will look at how we can configure multiple transport receivers and senders with WSO2 ESB and configure a proxy service to have multiple transport receivers.

In order to test our scenario, we need to start two message broker instances.

Lets configure active MQ to run as two instances.

1. Download activemq and extract it.
2. Run the following command to create an instance of it.

$ ./activemq create instanceA
$ ./activemq create instanceB


Running these two commands will create two directories inside activemq bin directory with configuration files and start-up scripts duplicated within them. Now we can modify the configuration files to use different ports so that when we start the two mq instances, there wont be port conflicts.

Open InstanceB/conf/activemq.xml file and modify the ports under transportConnectors.

<transportConnectors>
               <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireformat.maxFrameSize=104857600"/>
            <transportConnector name="amqp" uri="amqp://0.0.0.0:5682?maximumConnections=1000&amp;wireformat.maxFrameSize=104857600"/>
 </transportConnectors>


Now open jetty.xml in the same directory and modify the ui port from 8161 to different port.

Now we are ready to start the two activemq instances. 

cd instanceA/bin
./instanceA console

cd instanceB/bin
./instanceB console

Now we have two activemq instance running in console mode.

Log into activemq instanceA ui and create a queue named MyJMSQueue.
Similiary, log into activemq instanceB and create a queue with the same name.

Use http://localhost:8161/admin and username and password admin for defaults.

Now, we have done our configurations for activemq broker.

Now copy the following jar files to repository/components/lib directory of ESB.

activemq-broker-5.8.0.jar
activemq-client-5.8.0.jar
geronimo-j2ee-management_1.1_spec-1.0.1.jar
geronimo-jms_1.1_spec-1.1.1.jar
hawtbuf-1.9.jar


Configuring axis2.xml

Now go to repository/conf/axis2/axis2.xml and uncomment jms transport section for activemq and duplicate it with a transport named jms1. Make sure to update the provider url port with the value you specified in activemq.xml. My configuration looks like the following.

<transportReceiver name="jms" class="org.apache.axis2.transport.jms.JMSListener">
        <parameter name="myTopicConnectionFactory" locked="false">
                <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
                <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</parameter>
                <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">TopicConnectionFactory</parameter>
                    <parameter name="transport.jms.ConnectionFactoryType" locked="false">topic</parameter>
        </parameter>

        <parameter name="myQueueConnectionFactory" locked="false">
                <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
                <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</parameter>
                <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">QueueConnectionFactory</parameter>
                    <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>
        </parameter>

        <parameter name="default" locked="false">
                <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
                <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</parameter>
                <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">QueueConnectionFactory</parameter>
                    <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>
        </parameter>
    </transportReceiver>

    <transportReceiver name="jms1" class="org.apache.axis2.transport.jms.JMSListener">
        <parameter name="myTopicConnectionFactory1" locked="false">
                <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
                <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61636</parameter>
                <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">TopicConnectionFactory</parameter>
                    <parameter name="transport.jms.ConnectionFactoryType" locked="false">topic</parameter>
        </parameter>

        <parameter name="myQueueConnectionFactory1" locked="false">
                <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
                <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61636</parameter>
                <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">QueueConnectionFactory</parameter>
                    <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>
        </parameter>

        <parameter name="default" locked="false">
                <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
                <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61636</parameter>
                <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">QueueConnectionFactory</parameter>
                    <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>
        </parameter>


Now start ESB and deploy the following proxy service.

<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="JMSListenerProxy"
       transports="jms jms1"
       startOnLoad="true"
       trace="disable">
   <description/>
   <target>
      <inSequence>
         <log level="full"/>
         <drop/>
      </inSequence>
   </target>
   <parameter name="transport.jms.Destination">MyJMSQueue</parameter>
</proxy>

Now if you publish message to queue MyJMSQueue of either activemq instance, you will notice that the message is consumed by our proxy service and logged.

How does it work ?

In our scenario, since we are going to have to have different configurations for transports jms and jms1, we cannot specify the connection factory details in the proxy service itself. Hence we have resorted to use the default configurations specified in the axis2.xml.

However, we can specify the jms destination name in our proxy service. This make sense as this kind of approach would only be required for mq high availability scenario and hence we can afford to have the same queue name for both message broker instances. 

Saturday, March 28, 2015

How to configure IBM MQ 8 With WSO2 ESB

In this blog post, we will look at how to configure IBM MQ version 8 with WSO2 ESB and implement a proxy service to consume messages from a queue in IBM MQ.

Following are the steps we need to follow in order to configure ESB and implement our proxy service. 


1. Create the relevant JMS Administrative objects in IBM MQ.
2. Generate the JNDI binding file from IBM MQ
3. Configure WSO2 ESB JMS transport with the generated binding file and connection factory information.
4. Implement the proxy service and deploy it.
5. Publish a message to MQ and observe how it is consumed by ESB.

Create Queue Manager and Queue and Server Connection Channel in MQ

Step1.

Start the Web Sphere MQ Explorer. If you are not running on an administrator account, right click on the icon and select Run as Administrator option.


Step 2.

Click on the Queue Managers and Select New => Queue Manager to create a new queue manager.

We will name the queue manager as ESBQManager. Select create server connection channel option as you pass through the wizard with next button. You will get the option to specify the port this queue manager will use. Since we do not have any queue managers at the moment, we can use the default 1414 port.







Now we have created a queue manager object. Next we need to create a local queue which we will used to publish massages and consume from ESB. Lets name this queue as LocalQueue1.

Expand newly created ESBQManager and click on Queues and select New => Local Queue.





We will use default options for our local queue.

Next we need to create a server connection channel which will be used to connect to the queue manager.

Select Channels => New => Server-connection Channel option and give the channel name mychannel. Select default options for creating the channel.




Now we have created our queue manager, queue and server connection channel.

Generating the binding file

   Next we need to generate the binding file which will be used by IBM MQ client libraries for JNDI Look-up.  For that, we need to first create a directory where this binding file will be stored. I have created a directory named G:\jndidirectory for this purpose. 

Now go to MQ Explorer, click on JMS Administered Objects and select Add Initial Context.



In the connection details wizard, select File System option and browse to our newly created directory and click next and click finish.


Now, under the JMS Administered objects, we should be able to see our file initial context.



Expand it and click on Connection Factories to create a new connection factory.



We will name our connection factory as MyQueueConnectionFactory. For the connection factory type, select Queue Connection Factory.




Click next and click finish. Now Click on the newly created Connection Factory and select properties. Click on the connections option, browse and select our queue manager. You can also configure the port and the host name for connection factory. Since we used default values, we do not need to do any changes here. 






For the other options, go with the defaults. Next , we need to create a JMS Destination. We will use the same queue name LocalQueue1 as our destination and map it to our queue LocalQueue1 . Click on Destinations and select New => Destination. and provide name LocalQueue1. When you get the option to select the queue manager and queue browse and select ESBQManager and LocalQueue1 .





Now we are done with creating the Initial Context. If you now browse to the directory we specified, you should be able to see the newly generated binding file.



In order to connect to the Queue, we need to configure channel authentication. For the ease of use, lets disable channel authentication for our scenario. For that run the command runmqsc from the command line and execute the following two commands. Note that you have to start command prompt as admin user.

runmqsc ESBQManager

ALTER QMGR CHLAUTH(DISABLED)

REFRESH SECURITY TYPE(CONNAUTH)


Now we are done with configuring the IBM MQ.  

Configuring WSO2 ESB JMS Transport. 


open axis2.xml found in wso2esb-4.8.1\repository\conf\axis2 directory and add the following entries to it near the commented out jms transport receiver section.

<transportReceiver name="jms" class="org.apache.axis2.transport.jms.JMSListener">
  <parameter name="default" locked="false">
    <parameter name="java.naming.factory.initial" locked="false">com.sun.jndi.fscontext.RefFSContextFactory</parameter>
    <parameter name="java.naming.provider.url" locked="false">file:/G:/jndidirectory</parameter>
    <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">MyQueueConnectionFactory</parameter>
    <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>
    <parameter name="transport.jms.UserName" locked="false">nandika</parameter>
    <parameter name="transport.jms.Password" locked="false">password</parameter>
  </parameter>

  <parameter name="myQueueConnectionFactory1" locked="false">
    <parameter name="java.naming.factory.initial" locked="false">com.sun.jndi.fscontext.RefFSContextFactory</parameter>
    <parameter name="java.naming.provider.url" locked="false">file:/G:/jndidirectory</parameter>
    <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">MyQueueConnectionFactory</parameter>
    <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>
    <parameter name="transport.jms.UserName" locked="false">nandika</parameter>
    <parameter name="transport.jms.Password" locked="false">password</parameter>
  </parameter>
</transportReceiver>

Similarly add jms transport sender section as follows.

<transportSender name="jms" class="org.apache.axis2.transport.jms.JMSSender">
  <parameter name="default" locked="false">
    <parameter name="java.naming.factory.initial" locked="false">com.sun.jndi.fscontext.RefFSContextFactory</parameter>
    <parameter name="java.naming.provider.url" locked="false">file:/G:/jndidirectory</parameter>
    <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">MyQueueConnectionFactory</parameter>
    <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>
    <parameter name="transport.jms.UserName" locked="false">nandika</parameter>
    <parameter name="transport.jms.Password" locked="false">password</parameter>
  </parameter>

  <parameter name="myQueueConnectionFactory1" locked="false">
    <parameter name="java.naming.factory.initial" locked="false">com.sun.jndi.fscontext.RefFSContextFactory</parameter>
    <parameter name="java.naming.provider.url" locked="false">file:/G:/jndidirectory</parameter>
    <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">MyQueueConnectionFactory</parameter>
    <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>
    <parameter name="transport.jms.UserName" locked="false">nandika</parameter>
    <parameter name="transport.jms.Password" locked="false">password</parameter>
  </parameter>
</transportSender>

Since we are using IBM MQ queue manager default configuration, it is expecting username password client authentication. Here, the username and password is the login information of your logged in operating system account.


Copy MQ client libraries to respective directories.


Copy jta.jar and jms.jar to repository/components/lib directory.
Copy com.ibm.mq_2.0.0.jar and fscontext_1.0.0.jar to repository/components/dropins directory. Download the jar files from here.

Deploy JMSListener Proxy Service.

Now start esb and deploy the following simple proxy service. This proxy service act as a listener to our queue LocalQueue1 and when ever we put a message to this queue, the proxy service will pull that message out of the queue and log it.

<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="MyJMSProxy"
       transports="jms"
       startOnLoad="true"
       trace="disable">
   <description/>
   <target>
      <inSequence>
         <log level="full"/>
         <drop/>
      </inSequence>
   </target>
   <parameter name="transport.jms.Destination">LocalQueue1</parameter>
</proxy>

Testing our proxy service

Go to MQ Explorer and add a message to local queue. 



Now you will be able to see the message logged in ESB console as well as in the log file.

Enjoy JMS with IBM MQ

Sunday, December 21, 2014

Packt's $5 ebook Bonanza

Following the success of last year’s offer, Packt Publishing will be celebrating the holiday season with a bigger $5 offer. Check it out here  http://bit.ly/1DQhFk6 From Thursday 18th December, every eBook and video will be available on the publisher’s website for just $5. Customers are invited to purchase as many as they like before the offer ends on Tuesday January 6th, making it the perfect opportunity to try something new or to take your skills to the next level as 2015 begins.

Sunday, November 16, 2014

WS-BPEL 2.0 Beginner's Guide Book Review



I had the opportunity to read the WS-BPEL 2.0 Beginners Guide Book from PACKT publishing. The authors of this book has done a very good job in explaining the concepts in a simple and concise manner.

It is a very descriptive and practical guide to a beginners in BPEL. Writing an executable BPEL process is a very different task compared to write code in a general purpose programming language. The reason for that is, you need to have background knowledge on a lot of technologies in order to properly understand and implement a BPEL process. Minimum set of those technologies include SOAP / HTTP web services, WSDL, XML ,  Xml schema and XPath.

Hence , WS-BPEL 2.0 beginners guide takes an ideal approach for a beginner. It starts by introducing the basic concepts and straightaway goes into a practical example. It chooses oracle SOA Suite as the target technology stack and  JDeveloper  as its development environment for BPEL and provides step by step screen shots on how to implement a process.  Next it explains each and every step taken in implementing the sample process and how to deploy and test the process. I find this approach very useful, simply because, when learning a complex technology like BPEL, the best approach is to start with simple exercises to get the feel for the technology and then dive into the more complex topics step by step.

This pattern is followed for all the chapters as well. Each new chapter introduces a concept from BPEL, and goes onto a practical example explaining the details and finally testing the process. Hence, when you finish reading the book, not only you will understand the concepts in BPEL, but also, you would have mastered to BPEL development tool. As BPEL is developed mostly by using graphical tools, mastering the development environment is an essential skill for becoming a skilled BPEL developer.

The book explains the concepts in words as well as using diagrams. Book covers all the concepts from BPEL specification including topics such as synchronous processes, asynchronous processes, message correlation, fault handing , compensation handling ect.

In addition to BPEL concepts, book also covers the WS-Human Tasks space as well. The human tasks tooling capabilities of JDeveloper as well as the concepts are explained in a concise manner. In many practical process implementations in the industry there will be BPEL as well as human tasks. Hence for a beginner, this book is an ideal guide to master the BPEL based workflow technologies. Also, This book can be useful for an experienced BPEL developer migrating from another tool to JDeveloper.

Finally , I would recommend this book to anyone who is new to BPEL and is looking for a practical guide to learning BPEL related workflow technologies.   

Monday, February 24, 2014

Proxy Service Version Management with WSO2 ESB

Versioning of proxy services in an SOA environment is a common requirement. Versioning is required when you want to add / update or change the functionality of a proxy service without affecting the existing consumers of that proxy service. 




















Above diagram shows a typical versioning scenario. If the change in Service X 2.0 is compatible with Service X 1.0, then we can simply point to service X version 2.0 and consumers will not be affected by the change. However, if the change is in compatible, then we will have to introduce a new proxy service version.

General Principles of versioning

1. Client should not be forced to use the new version immediately
  • Gradual client migration
  • Retire services gracefully
2. Support multiple versions concurrently 
  • Limit the number of versions though governance
  • Only the latest version is discover-able

Solution 1. 

Create two versions of the proxy service. Consumer A can access the version 1.0 of the service and Consumer B can access version 2.0 of the service. Gradually migrate Consumer A to proxy service version 2.0. This way, consumer A can live with version 1.0 and plan for upgrading to version 2.0. Both versions of the proxy service will exist till version 1.0 is deprecated.
























Versioning with WSO2 ESB


Easiest way to version proxy services is to create a new version of the proxy service and related artifacts by appending the version information to the proxy service name. It is best to add version information to artifacts as a best practice. 

For example consider we have to  proxy a web service named StockQuote. Then we can name the proxy service as StockQuoteProxyV1. All artifacts contained with the proxy service should also be named accordingly. For example out endpoint pointing to the StockQuote service can be named as StockQuoteEndpointV1. 

Now creating and deploying new version of the proxy service becomes a simple task. We just need to update all the related artifacts with the new version number.


Future Improvements

Another approach to implementing proxy service versioning by having version as an attribute has been tried in the parent synapse project and there is a GSOC project on the same topic. These improvements are planed for future releases of WSO2 ESB.

References. 

Saturday, February 22, 2014

How to configure a BPEL process to consume JMS Queue

Since BPS is based on Axis2, All axis2 transports are available for BPEL published services as well. I will describe the steps required to consume a message from a JMS queue to complete a BPEL process.

We will use ActiveMQ for this sample.

Following is the step wise guide to do it.

Step 1. 
Download and extract Apache ActiveMQ 5.6.

Step 2.
Download Extract WSO2 BPS 3.2.0

Step 3.
un comment the TransportReceiver and TransportSender sections of axis2.xml corresponding to ActiveMQ. You can find axis2.xml located at /repository/conf/axis2 directory.


    <transportReceiver name="jms" class="org.apache.axis2.transport.jms.JMSListener">
        <parameter name="myTopicConnectionFactory">
                <parameter name="java.naming.factory.initial">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
                <parameter name="java.naming.provider.url">tcp://localhost:61616</parameter>
                <parameter name="transport.jms.ConnectionFactoryJNDIName">TopicConnectionFactory</parameter>
        </parameter>

        <parameter name="myQueueConnectionFactory">
                <parameter name="java.naming.factory.initial">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
                <parameter name="java.naming.provider.url">tcp://localhost:61616</parameter>
                <parameter name="transport.jms.ConnectionFactoryJNDIName">QueueConnectionFactory</parameter>
        </parameter>

        <parameter name="default">
                <parameter name="java.naming.factory.initial">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
                <parameter name="java.naming.provider.url">tcp://localhost:61616</parameter>
                <parameter name="transport.jms.ConnectionFactoryJNDIName">QueueConnectionFactory</parameter>
        </parameter>
    </transportReceiver>


<transportReceiver name="jms" class="org.apache.axis2.transport.jms.JMSListener">

Step 4.

Copy following jar files from activemq lib directory to /repository/components/lib directory.

activemq-core-5.6.0.jar
geronimo-j2ee-management_1.1_spec-1.0.1.jar
geronimo-jms_1.1_spec-1.1.1.jar


Step 5.
Start active mq from console

apache-activemq-5.6.0/bin $ ./activemq console
Use management console of ActiveMQ to view the queues and topics. ActiveMQ management console is available at http://0.0.0.0:8161/admin



Step 6.
Start BPS from console.

wso2bps-3.2.0/bin $ sh wso2server.sh

From the management console , deploy the HelloWorld2.zip file that is available in the repository/samples/bpel directory of BPS.

From the services list view, select the HelloWorld service. 



As you can see, the jms endpoint is also available for the newly deployed process. 

Step 7.

Now go to ActiveMQ management console and go to queues section. You will find that there is a queue named HelloService. 






Use the send to section to add a message to the HelloService. You can generate the sample message for the HelloService wsdl using soap ui.