Monday, August 19, 2013

Active 5.8.0 Master Slave Web Console Fix

Recently I ran into an issue when I attempted to use ActiveMQ 5.8.0 Web Console to monitor a two node Master/Slave ActiveMQ cluster.

The ActiveMQ 5.8.0 Web Console (hosted in a Tomcat container) connects to remote ActiveMQ instance over JMX. In ActiveMQ 5.8.0, the JMX connector is enabled for both Master and Slave nodes. Due to which the Web Console is unable to determine which node is the master node. Hence the issue. 

In order to get around this problem, I created a class which extends the RemoteJMXBrokerFacade class by adding intelligence to an overridden findBrokers(...) method such that the Web Console considers an ActiveMQ node as a master node if and only if it is able to fetch a reference to the BrokerViewMBean. 

The above operation throws an IllegalStateException if the broker was to be slave node. 

The Web Console gets the list of JMX Connectors for all the ActiveMQ Brokers in a cluster via the following property


-Dwebconsole.jmx.url=service:jmx:rmi:///jndi/rmi://amq-node-1-machine:12099/jmxrmi,service:jmx:rmi:///jndi/rmi://amq-node-2-machine:12099/jmxrmi

The following is the source code:

package org.apache.activemq.web;

import java.io.IOException;
import java.util.Set;

import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

import org.apache.activemq.broker.jmx.BrokerViewMBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class helps ActiveMQ Web Console determine if the remote broker instance is master or slave
 * 
 * In the webconsole-properties.xml, replace the <code>org.apache.activemq.web.RemoteJMXBrokerFacade</code> class 
 * with <code>org.apache.activemq.web.MasterSlaveAwareJMXBrokerFacade</code>
 * <pre>
 * {@code
 *  <bean id="brokerQuery" class="org.apache.activemq.web.MasterSlaveAwareJMXBrokerFacade" autowire="constructor" destroy-method="shutdown">
    <property name="configuration" ref="configuration"/>
    <property name="brokerName"><null/></property>
   </bean>
 * }
 * </pre>
 * @author AKUNTAMUKKALA
 *
 */
public class MasterSlaveAwareJMXBrokerFacade extends RemoteJMXBrokerFacade {

 private static final transient Logger LOG = LoggerFactory
   .getLogger(MasterSlaveAwareJMXBrokerFacade.class);

 @Override
 protected Set<ObjectName> findBrokers(MBeanServerConnection connection)
   throws IOException, MalformedObjectNameException {

  LOG.debug("Finding brokers");
  ObjectName name;

  name = new ObjectName("org.apache.activemq:type=Broker,brokerName=*");

  Set<ObjectName> brokers = connection.queryNames(name, null);
  

  try {
   ObjectName brokerObjectName = (ObjectName) brokers.iterator().next();
   BrokerViewMBean mbean = (BrokerViewMBean) MBeanServerInvocationHandler
     .newProxyInstance(connection, brokerObjectName,
       BrokerViewMBean.class, true);

   LOG.debug("Broker Id : " + mbean.getBrokerId());

  } catch (Throwable t) {
   // TODO Auto-generated catch block
   LOG.error("Exception occurred while trying to retrieve BrokerViewMBean", t);
   throw new RuntimeException(t);
  }
  return brokers;
 }

}

If the Web Console attempts to connect to slave broker, the following exception gets thrown.
SEVERE: Servlet.service() for servlet [jsp] in context with path [/activemq-web-console-5.8.0] threw exception [javax.el.ELException: Error reading 'brokerName' on type org.apache.activemq.web.RemoteJMXBrokerFacade] with root cause
java.lang.IllegalStateException: Broker is not yet started.
 at org.apache.activemq.broker.jmx.BrokerView.safeGetBroker(BrokerView.java:459)
 at org.apache.activemq.broker.jmx.BrokerView.getBrokerName(BrokerView.java:75)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at com.sun.jmx.mbeanserver.StandardMBeanIntrospector.invokeM2(StandardMBeanIntrospector.java:93)
 at com.sun.jmx.mbeanserver.StandardMBeanIntrospector.invokeM2(StandardMBeanIntrospector.java:27)
 at com.sun.jmx.mbeanserver.MBeanIntrospector.invokeM(MBeanIntrospector.java:208)
 at com.sun.jmx.mbeanserver.PerInterface.getAttribute(PerInterface.java:65)
 at com.sun.jmx.mbeanserver.MBeanSupport.getAttribute(MBeanSupport.java:216)
 at javax.management.StandardMBean.getAttribute(StandardMBean.java:358)
 at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.java:666)
 at com.sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.java:638)
 at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1404)
 at javax.management.remote.rmi.RMIConnectionImpl.access$200(RMIConnectionImpl.java:72)
 at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1265)
 at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1360)
 at javax.management.remote.rmi.RMIConnectionImpl.getAttribute(RMIConnectionImpl.java:600)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:303)
 at sun.rmi.transport.Transport$1.run(Transport.java:159)
 at java.security.AccessController.doPrivileged(Native Method)
 at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
 at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
 at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
 at java.lang.Thread.run(Thread.java:662)


This solution has worked for me. I would like to know if you have a better way to fix this.

Tuesday, July 9, 2013

Using ActiveMQ - "Master/Slave" configuration with failover protocol


Objective:

This blog is to share how to run highly available ActiveMQ cluster in Master/Slave configuration.

Introduction:

ActiveMQ broker(s) tends to be a core piece of messaging infrastructure in an enterprise. It is vital for this messaging infrastructure to be highly available and scalable. Please read this link in order to learn more about creating network of brokers to support various use cases. One of the popular use case for ActiveMQ is the Master/Slave configuration with shared database. When this configuration is used, the message consumers and producers can operate without interruptions as they use ActiveMQ's connection factory with failover protocol. The failover protocol insulates the consumers and producers from having to deal with any potential downtime or application level reconnection logic when slave ActiveMQ node takes over to become the master which happens if the current master node goes down for any reason. I must caution that this configuration must not be used to mask any issues which take out the master node. We should iron out any causes that result in an unplanned master node outage.

Overview:

In this blog, I will demonstrate the following:
  1. Run 2 ActiveMQ nodes in a Master/Slave configuration with a shared KahaDB file based database. 
  2. Configure ActiveMQ web console hosted in a Tomcat instance to point to whichever node is Master node in the cluster.
  3. Failover scenarios.
  4. Message publisher and consumer behavior oblivious to the failover.

Prerequisites:
  1. Install ActiveMQ version 5.8.0 
  2. Download ActiveMQ version 5.8.0 web console war from here 
  3. Install Tomcat version 7.0.35 - To host the ActiveMQ Web Console application
Deep Dive:

We will create a 2 node ActiveMQ cluster on the same Windows 7 machine. We will need to configure the ports (TCP & JMX) such that there is no conflict. ActiveMQ provides a script called "activemq-admin.bat" which helps in running multiple instances of ActiveMQ using the same binaries, very much like Tomcat. Let's go ahead and create broker-1 and broker-2 instances.

command: activemq-admin create <DIR-for-ActiveMQ-node>

C:\apache-activemq-5.8.0\bin>activemq-admin create ..\cluster\broker-1

Java Runtime: Sun Microsystems Inc. 1.6.0_31 C:\Program Files\Java\jdk1.6.0_31\jre
  Heap sizes: current=125632k  free=124976k  max=1864192k
    JVM args: -Dactivemq.classpath=C:\apache-activemq-5.8.0\bin\..\conf;C:\apache-activemq-5.8.0\bin\..\data; -Dactivemq.home=C:\apache-activemq-5.8.0
\bin\.. -Dactivemq.base=C:\apache-activemq-5.8.0\bin\.. -Dactivemq.data=C:\apache-activemq-5.8.0\bin\..\data -Djava.io.tmpdir=C:\apache-activemq-5.8.0
\bin\..\data\tmp -Dactivemq.conf=C:\apache-activemq-5.8.0\bin\..\conf
Extensions classpath:
  [C:\apache-activemq-5.8.0\bin\..\lib,C:\apache-activemq-5.8.0\bin\..\lib\camel,C:\apache-activemq-5.8.0\bin\..\lib\optional,C:\apache-activemq-5.8.0
\bin\..\lib\web,C:\apache-activemq-5.8.0\bin\..\lib\extra]
ACTIVEMQ_HOME: C:\apache-activemq-5.8.0\bin\..
ACTIVEMQ_BASE: C:\apache-activemq-5.8.0\bin\..
ACTIVEMQ_CONF: C:\apache-activemq-5.8.0\bin\..\conf
ACTIVEMQ_DATA: C:\apache-activemq-5.8.0\bin\..\data
Running create broker task...
Creating directory: C:\apache-activemq-5.8.0\cluster\broker-1
Creating directory: C:\apache-activemq-5.8.0\cluster\broker-1\bin
Creating directory: C:\apache-activemq-5.8.0\cluster\broker-1\conf
Creating new file: C:\apache-activemq-5.8.0\cluster\broker-1\bin\broker-1.bat
Creating new file: C:\apache-activemq-5.8.0\cluster\broker-1\bin\broker-1
Copying from: C:\apache-activemq-5.8.0\conf\activemq.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\activemq.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-command.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\activemq-command.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-demo.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\activemq-demo.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-dynamic-network-broker1.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\activemq-dynamic-network-broker1.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-dynamic-network-broker2.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\activemq-dynamic-network-broker2.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-jdbc.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\activemq-jdbc.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-scalability.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\activemq-scalability.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-security.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\activemq-security.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-specjms.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\activemq-specjms.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-static-network-broker1.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\activemq-static-network-broker1.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-static-network-broker2.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\activemq-static-network-broker2.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-stomp.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\activemq-stomp.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-throughput.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\activemq-throughput.xml
Copying from: C:\apache-activemq-5.8.0\conf\broker-localhost.cert
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\broker-localhost.cert
Copying from: C:\apache-activemq-5.8.0\conf\broker.ks
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\broker.ks
Copying from: C:\apache-activemq-5.8.0\conf\broker.ts
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\broker.ts
Copying from: C:\apache-activemq-5.8.0\conf\camel.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\camel.xml
Copying from: C:\apache-activemq-5.8.0\conf\client.ks
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\client.ks
Copying from: C:\apache-activemq-5.8.0\conf\client.ts
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\client.ts
Copying from: C:\apache-activemq-5.8.0\conf\credentials-enc.properties
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\credentials-enc.properties
Copying from: C:\apache-activemq-5.8.0\conf\credentials.properties
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\credentials.properties
Copying from: C:\apache-activemq-5.8.0\conf\jetty-demo.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\jetty-demo.xml
Copying from: C:\apache-activemq-5.8.0\conf\jetty-realm.properties
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\jetty-realm.properties
Copying from: C:\apache-activemq-5.8.0\conf\jetty.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\jetty.xml
Copying from: C:\apache-activemq-5.8.0\conf\jmx.access
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\jmx.access
Copying from: C:\apache-activemq-5.8.0\conf\jmx.password
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\jmx.password
Copying from: C:\apache-activemq-5.8.0\conf\log4j.properties
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\log4j.properties
Copying from: C:\apache-activemq-5.8.0\conf\logging.properties
          to: C:\apache-activemq-5.8.0\cluster\broker-1\conf\logging.properties

 Now let's create broker-2 instance...

C:\apache-activemq-5.8.0\bin>activemq-admin create ..\cluster\broker-2

Java Runtime: Sun Microsystems Inc. 1.6.0_31 C:\Program Files\Java\jdk1.6.0_31\jre
  Heap sizes: current=125632k  free=124976k  max=1864192k
    JVM args: -Dactivemq.classpath=C:\apache-activemq-5.8.0\bin\..\conf;C:\apache-activemq-5.8.0\bin\..\data; -Dactivemq.home=C:\apache-activemq-5.8.0
\bin\.. -Dactivemq.base=C:\apache-activemq-5.8.0\bin\.. -Dactivemq.data=C:\apache-activemq-5.8.0\bin\..\data -Djava.io.tmpdir=C:\apache-activemq-5.8.0
\bin\..\data\tmp -Dactivemq.conf=C:\apache-activemq-5.8.0\bin\..\conf
Extensions classpath:
  [C:\apache-activemq-5.8.0\bin\..\lib,C:\apache-activemq-5.8.0\bin\..\lib\camel,C:\apache-activemq-5.8.0\bin\..\lib\optional,C:\apache-activemq-5.8.0
\bin\..\lib\web,C:\apache-activemq-5.8.0\bin\..\lib\extra]
ACTIVEMQ_HOME: C:\apache-activemq-5.8.0\bin\..
ACTIVEMQ_BASE: C:\apache-activemq-5.8.0\bin\..
ACTIVEMQ_CONF: C:\apache-activemq-5.8.0\bin\..\conf
ACTIVEMQ_DATA: C:\apache-activemq-5.8.0\bin\..\data
Running create broker task...
Creating directory: C:\apache-activemq-5.8.0\cluster\broker-2
Creating directory: C:\apache-activemq-5.8.0\cluster\broker-2\bin
Creating directory: C:\apache-activemq-5.8.0\cluster\broker-2\conf
Creating new file: C:\apache-activemq-5.8.0\cluster\broker-2\bin\broker-2.bat
Creating new file: C:\apache-activemq-5.8.0\cluster\broker-2\bin\broker-2
Copying from: C:\apache-activemq-5.8.0\conf\activemq.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\activemq.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-command.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\activemq-command.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-demo.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\activemq-demo.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-dynamic-network-broker1.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\activemq-dynamic-network-broker1.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-dynamic-network-broker2.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\activemq-dynamic-network-broker2.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-jdbc.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\activemq-jdbc.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-scalability.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\activemq-scalability.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-security.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\activemq-security.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-specjms.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\activemq-specjms.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-static-network-broker1.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\activemq-static-network-broker1.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-static-network-broker2.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\activemq-static-network-broker2.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-stomp.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\activemq-stomp.xml
Copying from: C:\apache-activemq-5.8.0\conf\activemq-throughput.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\activemq-throughput.xml
Copying from: C:\apache-activemq-5.8.0\conf\broker-localhost.cert
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\broker-localhost.cert
Copying from: C:\apache-activemq-5.8.0\conf\broker.ks
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\broker.ks
Copying from: C:\apache-activemq-5.8.0\conf\broker.ts
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\broker.ts
Copying from: C:\apache-activemq-5.8.0\conf\camel.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\camel.xml
Copying from: C:\apache-activemq-5.8.0\conf\client.ks
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\client.ks
Copying from: C:\apache-activemq-5.8.0\conf\client.ts
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\client.ts
Copying from: C:\apache-activemq-5.8.0\conf\credentials-enc.properties
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\credentials-enc.properties
Copying from: C:\apache-activemq-5.8.0\conf\credentials.properties
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\credentials.properties
Copying from: C:\apache-activemq-5.8.0\conf\jetty-demo.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\jetty-demo.xml
Copying from: C:\apache-activemq-5.8.0\conf\jetty-realm.properties
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\jetty-realm.properties
Copying from: C:\apache-activemq-5.8.0\conf\jetty.xml
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\jetty.xml
Copying from: C:\apache-activemq-5.8.0\conf\jmx.access
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\jmx.access
Copying from: C:\apache-activemq-5.8.0\conf\jmx.password
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\jmx.password
Copying from: C:\apache-activemq-5.8.0\conf\log4j.properties
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\log4j.properties
Copying from: C:\apache-activemq-5.8.0\conf\logging.properties
          to: C:\apache-activemq-5.8.0\cluster\broker-2\conf\logging.properties

You may have noticed the following properties above: 

ACTIVEMQ_BASE: C:\apache-activemq-5.8.0\bin\..
ACTIVEMQ_CONF: C:\apache-activemq-5.8.0\bin\..\conf
ACTIVEMQ_DATA: C:\apache-activemq-5.8.0\bin\..\data

These properties need to be fixed as we'd like ACTIVEMQ_BASE and ACTIVEMQ_CONF to be different for both broker-1 and broker-2.

We need to edit the following files:
  • broker-1.bat in C:\apache-activemq-5.8.0\cluster\broker-1\bin directory
    • set ACTIVEMQ_HOME="C:/apache-activemq-5.8.0" 
    • set ACTIVEMQ_BASE="C:/apache-activemq-5.8.0/cluster/broker-1"
    • set ACTIVEMQ_CONF=%ACTIVEMQ_BASE%/conf 
  • broker-2.bat in C:\apache-activemq-5.8.0\cluster\broker-2\bin directory 
    • set ACTIVEMQ_HOME="C:/apache-activemq-5.8.0"
    • set ACTIVEMQ_BASE="C:/apache-activemq-5.8.0/cluster/broker-2"
    • set ACTIVEMQ_CONF=%ACTIVEMQ_BASE%/conf
You may observe that both broker-1 and broker-2 nodes share the same ACTIVEMQ_DATA folder. Since we are using the in-built KahaDB for persistence, both broker-1 and broker-2 will share this.

We need to differentiate the tcp ports for broker-1 and broker-2 and also enable JMX and configure  JMX ports for remote monitoring.

Let's edit the activemq.xml for broker-1 to fix tcp port:

        <transportConnectors>
            <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
            <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:5672?maximumConnections=1000&amp;wireformat.maxFrameSize=104857600"/>-->
        </transportConnectors>
Let's edit the activemq.xml for broker-1 to enable JMX monitoring, notice useJMX="true" attribute below.
        <broker xmlns="http://activemq.apache.org/schema/core" brokerName="broker-1" dataDirectory="${activemq.data}" useJmx="true">
Let's configure the JMX port
        <managementContext>
            <managementContext createConnector="true" connectorPort="1099"/>
        </managementContext>

Repeat the same for broker-2. set TCP port to 61626 and JMX port to 2099.

Start broker-1.

C:\apache-activemq-5.8.0\cluster\broker-1\bin>broker-1.bat
Java Runtime: Sun Microsystems Inc. 1.6.0_31 C:\Program Files\Java\jdk1.6.0_31\jre
  Heap sizes: current=1004928k  free=994439k  max=1004928k
    JVM args: -Dcom.sun.management.jmxremote -Xms1G -Xmx1G -Djava.util.logging.config.file=logging.properties -Dactivemq.classpath=C:/apache-activemq-
5.8.0/cluster/broker-1/conf;C:/apache-activemq-5.8.0/cluster/broker-1/conf;C:/apache-activemq-5.8.0/conf; -Dactivemq.home=C:/apache-activemq-5.8.0 -Da
ctivemq.base=C:/apache-activemq-5.8.0/cluster/broker-1 -Dactivemq.conf=C:/apache-activemq-5.8.0/cluster/broker-1/conf -Dactivemq.data=C:/apache-active
mq-5.8.0\data -Djava.io.tmpdir=C:/apache-activemq-5.8.0\data\tmp
Extensions classpath:
  [C:\apache-activemq-5.8.0\cluster\broker-1\lib,C:\apache-activemq-5.8.0\lib,C:\apache-activemq-5.8.0\cluster\broker-1\lib\camel,C:\apache-activemq-5
.8.0\cluster\broker-1\lib\optional,C:\apache-activemq-5.8.0\cluster\broker-1\lib\web,C:\apache-activemq-5.8.0\cluster\broker-1\lib\extra,C:\apache-act
ivemq-5.8.0\lib\camel,C:\apache-activemq-5.8.0\lib\optional,C:\apache-activemq-5.8.0\lib\web,C:\apache-activemq-5.8.0\lib\extra]
ACTIVEMQ_HOME: C:\apache-activemq-5.8.0
ACTIVEMQ_BASE: C:\apache-activemq-5.8.0\cluster\broker-1
ACTIVEMQ_CONF: C:\apache-activemq-5.8.0\cluster\broker-1\conf
ACTIVEMQ_DATA: C:\apache-activemq-5.8.0\data
Loading message broker from: xbean:activemq.xml
 INFO | Refreshing org.apache.activemq.xbean.XBeanBrokerFactory$1@71060478: startup date [Tue Jul 09 16:59:15 CDT 2013]; root of context hierarchy
 INFO | PListStore:[C:\apache-activemq-5.8.0\data\broker-1\tmp_storage] started
 INFO | Using Persistence Adapter: KahaDBPersistenceAdapter[C:\apache-activemq-5.8.0\data\kahadb]
 INFO | JMX consoles can connect to service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi
 INFO | KahaDB is version 4
 INFO | Recovering from the journal ...
 INFO | Recovery replayed 1 operations from the journal in 0.028 seconds.
 INFO | Apache ActiveMQ 5.8.0 (broker-1, ID:AKUNTAMU-1-27777-1373407157813-0:1) is starting
 INFO | Listening for connections at: tcp://AKUNTAMU-1:61616?maximumConnections=1000&wireformat.maxFrameSize=104857600
 INFO | Connector openwire Started
 INFO | Apache ActiveMQ 5.8.0 (broker-1, ID:AKUNTAMU-1-27777-1373407157813-0:1) started
 INFO | For help or more information please see: http://activemq.apache.org
 WARN | Store limit is 102400 mb, whilst the data directory: C:\apache-activemq-5.8.0\data\kahadb only has 38889 mb of usable space
ERROR | Temporary Store limit is 51200 mb, whilst the temporary data directory: C:\apache-activemq-5.8.0\data\broker-1\tmp_storage only has 38889 mb o
f usable space
 INFO | Web console type: embedded
 INFO | ActiveMQ WebConsole initialized.
 INFO | Initializing Spring FrameworkServlet 'dispatcher'
 INFO | jolokia-agent: No access restrictor found at classpath:/jolokia-access.xml, access to all MBeans is allowed

Start broker-2.

You will observe that broker-2 is unable to acquire the lock since broker-1 already grabbed it. broker-2 will keep retrying to acquire the lock every 10 seconds.

C:\apache-activemq-5.8.0\cluster\broker-2\bin>broker-2.bat
Java Runtime: Sun Microsystems Inc. 1.6.0_31 C:\Program Files\Java\jdk1.6.0_31\jre
  Heap sizes: current=1004928k  free=994439k  max=1004928k
    JVM args: -Dcom.sun.management.jmxremote -Xms1G -Xmx1G -Djava.util.logging.config.file=logging.properties -Dactivemq.classpath=C:/apache-activemq-
5.8.0/cluster/broker-2/conf;C:/apache-activemq-5.8.0/cluster/broker-2/conf;C:/apache-activemq-5.8.0/conf; -Dactivemq.home=C:/apache-activemq-5.8.0 -Da
ctivemq.base=C:/apache-activemq-5.8.0/cluster/broker-2 -Dactivemq.conf=C:/apache-activemq-5.8.0/cluster/broker-2/conf -Dactivemq.data=C:/apache-active
mq-5.8.0\data -Djava.io.tmpdir=C:/apache-activemq-5.8.0\data\tmp
Extensions classpath:
  [C:\apache-activemq-5.8.0\cluster\broker-2\lib,C:\apache-activemq-5.8.0\lib,C:\apache-activemq-5.8.0\cluster\broker-2\lib\camel,C:\apache-activemq-5
.8.0\cluster\broker-2\lib\optional,C:\apache-activemq-5.8.0\cluster\broker-2\lib\web,C:\apache-activemq-5.8.0\cluster\broker-2\lib\extra,C:\apache-act
ivemq-5.8.0\lib\camel,C:\apache-activemq-5.8.0\lib\optional,C:\apache-activemq-5.8.0\lib\web,C:\apache-activemq-5.8.0\lib\extra]
ACTIVEMQ_HOME: C:\apache-activemq-5.8.0
ACTIVEMQ_BASE: C:\apache-activemq-5.8.0\cluster\broker-2
ACTIVEMQ_CONF: C:\apache-activemq-5.8.0\cluster\broker-2\conf
ACTIVEMQ_DATA: C:\apache-activemq-5.8.0\data
Loading message broker from: xbean:activemq.xml
 INFO | Refreshing org.apache.activemq.xbean.XBeanBrokerFactory$1@420f9c40: startup date [Tue Jul 09 17:02:55 CDT 2013]; root of context hierarchy
 INFO | PListStore:[C:\apache-activemq-5.8.0\data\broker-2\tmp_storage] started
 INFO | Using Persistence Adapter: KahaDBPersistenceAdapter[C:\apache-activemq-5.8.0\data\kahadb]
 INFO | Database C:\apache-activemq-5.8.0\data\kahadb\lock is locked... waiting 10 seconds for the database to be unlocked. Reason: java.io.IOExceptio
n: File 'C:\apache-activemq-5.8.0\data\kahadb\lock' could not be locked.
 INFO | JMX consoles can connect to service:jmx:rmi:///jndi/rmi://localhost:2099/jmxrmi
 INFO | Database C:\apache-activemq-5.8.0\data\kahadb\lock is locked... waiting 10 seconds for the database to be unlocked. Reason: java.io.IOExceptio
n: File 'C:\apache-activemq-5.8.0\data\kahadb\lock' could not be locked.
 INFO | Database C:\apache-activemq-5.8.0\data\kahadb\lock is locked... waiting 10 seconds for the database to be unlocked. Reason: java.io.IOExceptio
n: File 'C:\apache-activemq-5.8.0\data\kahadb\lock' could not be locked.

Now let's configure the ActiveMQ web console.
By default, ActiveMQ distribution contains admin web console but in the Master/Slave configuration, it is unknown which node is the master. So it is doesn't make sense to use the embedded web console. Hence it is best to have ActiveMQ web console outside of the ActiveMQ nodes.

You can disable the embedded ActiveMQ Web Console in each node by commenting the following line in activemq.xml in conf directory of each ActiveMQ node.

<!--<import resource="jetty.xml"/>-->

For our example, we will deploy ActiveMQ Web Console web application in Tomcat container and then configure ActiveMQ web console application to intelligently point to the master node in ActiveMQ cluster.

so let's copy the activemq-web-console-5.8.0.war to webapps directory of Tomcat. Add the following line to catalina.bat 

set JAVA_OPTS=-Dwebconsole.type=properties -Dwebconsole.jms.url=failover:(tcp://localhost:61616,tcp://localhost:61626) -Dwebconsole.jmx.url=service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi,service:jmx:rmi:///jndi/rmi://localhost:2099/jmxrmi

Now let's start Tomcat.

C:\apache-tomcat-7.0.35\bin>.\catalina.bat run
Using CATALINA_BASE:   "C:\apache-tomcat-7.0.35"
Using CATALINA_HOME:   "C:\apache-tomcat-7.0.35"
Using CATALINA_TMPDIR: "C:\apache-tomcat-7.0.35\temp"
Using JRE_HOME:        "C:\Program Files\Java\jdk1.6.0_31"
Using CLASSPATH:       "C:\apache-tomcat-7.0.35\bin\bootstrap.jar;C:\apache-tomcat-7.0.35\bin\tomcat-juli.jar"
Jul 9, 2013 5:28:08 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-bio-8080"]
Jul 9, 2013 5:28:08 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["ajp-bio-8009"]
Jul 9, 2013 5:28:08 PM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 635 ms
Jul 9, 2013 5:28:08 PM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Catalina
Jul 9, 2013 5:28:08 PM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.35
Jul 9, 2013 5:28:08 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive C:\apache-tomcat-7.0.35\webapps\activemq-web-console-5.8.0.war
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/apache-tomcat-7.0.35/webapps/activemq-web-console-5.8.0/WEB-INF/lib/activemq-all-5.8.0.jar!/org/slf4j/impl/Stati
cLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/apache-tomcat-7.0.35/webapps/activemq-web-console-5.8.0/WEB-INF/lib/slf4j-log4j12-1.6.6.jar!/org/slf4j/impl/Stat
icLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
2013-07-09 17:28:13,389 [ost-startStop-1] INFO  WebConsoleStarter              - Web console type: properties
2013-07-09 17:28:13,960 [ost-startStop-1] INFO  WebConsoleStarter              - ActiveMQ WebConsole initialized.
2013-07-09 17:28:14,095 [ost-startStop-1] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/createDestination.action] onto handler '/createDest
ination.action'
2013-07-09 17:28:14,096 [ost-startStop-1] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/deleteDestination.action] onto handler '/deleteDest
ination.action'
2013-07-09 17:28:14,097 [ost-startStop-1] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/createSubscriber.action] onto handler '/createSubsc
riber.action'
2013-07-09 17:28:14,098 [ost-startStop-1] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/deleteSubscriber.action] onto handler '/deleteSubsc
riber.action'
2013-07-09 17:28:14,099 [ost-startStop-1] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/sendMessage.action] onto handler '/sendMessage.acti
on'
2013-07-09 17:28:14,100 [ost-startStop-1] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/purgeDestination.action] onto handler '/purgeDestin
ation.action'
2013-07-09 17:28:14,101 [ost-startStop-1] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/deleteMessage.action] onto handler '/deleteMessage.
action'
2013-07-09 17:28:14,103 [ost-startStop-1] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/copyMessage.action] onto handler '/copyMessage.acti
on'
2013-07-09 17:28:14,104 [ost-startStop-1] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/moveMessage.action] onto handler '/moveMessage.acti
on'
2013-07-09 17:28:14,105 [ost-startStop-1] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/deleteJob.action] onto handler '/deleteJob.action'
Jul 9, 2013 5:28:14 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory C:\apache-tomcat-7.0.35\webapps\docs
Jul 9, 2013 5:28:14 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory C:\apache-tomcat-7.0.35\webapps\examples
Jul 9, 2013 5:28:14 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory C:\apache-tomcat-7.0.35\webapps\host-manager
Jul 9, 2013 5:28:14 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory C:\apache-tomcat-7.0.35\webapps\manager
Jul 9, 2013 5:28:14 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory C:\apache-tomcat-7.0.35\webapps\ROOT
Jul 9, 2013 5:28:14 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
Jul 9, 2013 5:28:14 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
Jul 9, 2013 5:28:14 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 6642 ms

Let's access the web console: http://localhost:8080/activemq-web-console-5.8.0
Use admin/admin for username/password if prompted. These are default security settings. Refer jetty.xml and jetty-realm.properties in conf directory.


As shown above, "broker-1" is the current master broker.

Now, if you were to shutdown broker-1. Hit Control+C on Terminal window running broker-1, you'd notice that broker-2 acquires the lock and becomes the master.
 INFO | Database C:\apache-activemq-5.8.0\data\kahadb\lock is locked... waiting 10 seconds for the database to be unlocked. Reason: java.io.IOExceptio
n: File 'C:\apache-activemq-5.8.0\data\kahadb\lock' could not be locked.
 INFO | Database C:\apache-activemq-5.8.0\data\kahadb\lock is locked... waiting 10 seconds for the database to be unlocked. Reason: java.io.IOExceptio
n: File 'C:\apache-activemq-5.8.0\data\kahadb\lock' could not be locked.
 INFO | Database C:\apache-activemq-5.8.0\data\kahadb\lock is locked... waiting 10 seconds for the database to be unlocked. Reason: java.io.IOExceptio
n: File 'C:\apache-activemq-5.8.0\data\kahadb\lock' could not be locked.
 INFO | Database C:\apache-activemq-5.8.0\data\kahadb\lock is locked... waiting 10 seconds for the database to be unlocked. Reason: java.io.IOExceptio
n: File 'C:\apache-activemq-5.8.0\data\kahadb\lock' could not be locked.
 INFO | KahaDB is version 4
 INFO | Recovering from the journal ...
 INFO | Recovery replayed 2 operations from the journal in 0.022 seconds.
 INFO | Apache ActiveMQ 5.8.0 (broker-2, ID:AKUNTAMU-1-28147-1373409767675-0:1) is starting
 INFO | Listening for connections at: tcp://AKUNTAMU-1:61626?maximumConnections=1000&wireformat.maxFrameSize=104857600
 INFO | Connector openwire Started
 INFO | Apache ActiveMQ 5.8.0 (broker-2, ID:AKUNTAMU-1-28147-1373409767675-0:1) started
 INFO | For help or more information please see: http://activemq.apache.org
 WARN | Store limit is 102400 mb, whilst the data directory: C:\apache-activemq-5.8.0\data\kahadb only has 38888 mb of usable space
ERROR | Temporary Store limit is 51200 mb, whilst the temporary data directory: C:\apache-activemq-5.8.0\data\broker-2\tmp_storage only has 38888 mb o
f usable space
 INFO | Web console type: embedded
 INFO | ActiveMQ WebConsole initialized.
 INFO | Initializing Spring FrameworkServlet 'dispatcher'
 INFO | jolokia-agent: No access restrictor found at classpath:/jolokia-access.xml, access to all MBeans is allowed

Let's refresh the web console

 

As you may observe, now the master node is broker-2. 

Now that we have seen seamless switch over between the nodes during a failover scenario using an external web console, let's see the same from the perspective of a message producer and consumer.

I will publish 50 persistent messages to a queue using a simple message publisher and have an asynchronous consumer receive those 50 messages. I will introduce a bit of a delay in sending the messages so we can take the master down a few times and create a few failover scenarios. The objective is to see how the failover protocol makes the node failover completely transparent and thus shields the application from having to deal with any reconnection logic.

Here is a simple producer using ActiveMQConnectionFactory with failover protocol. Notice the highlighted failover protocol URL in the code snippet below.

package com.akuntamukkala.amqms;

import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.log4j.Logger;


public class Producer {

	private static final Logger	log = Logger.getLogger(Producer.class);
	
	public static void main(String[] args) throws Exception {
		// Create a ConnectionFactory
		ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
				"failover:(tcp://localhost:61616,tcp://localhost:61626)");

		for (int i = 0; i < 50; i++) {
			
			log.info("Establishing connection");
			// Create a Connection
			Connection connection = connectionFactory.createConnection();
			connection.start();
			
			log.info("Connection established");
			
			// Create a Session
			Session session = connection.createSession(false,
					Session.AUTO_ACKNOWLEDGE);

			// Create the destination (Topic or Queue)
			Destination destination = session.createQueue("TEST.FOO");

			// Create a MessageProducer from the Session to the Topic or Queue
			MessageProducer producer = session.createProducer(destination);
			producer.setDeliveryMode(DeliveryMode.PERSISTENT);

			// Create a messages
			String text = "Message Counter : " + i;
			TextMessage message = session.createTextMessage(text);

			log.info("Sending message : " + text);
			producer.send(message);
			log.info("Sent message : " + text);
			// Clean up
			session.close();
			connection.close();

			Thread.sleep(1000);
		}
	}
}

Here are the logs from execution while I shutdown broker-1 and broker-2 alternatively a few times.

2013-07-10 11:26:32 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:33 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:26:33 INFO  Producer:30 - Connection established
2013-07-10 11:26:33 INFO  Producer:47 - Sending message : Message Counter : 0
2013-07-10 11:26:33 INFO  Producer:49 - Sent message : Message Counter : 0
2013-07-10 11:26:34 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:35 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:26:35 INFO  Producer:30 - Connection established
2013-07-10 11:26:35 INFO  Producer:47 - Sending message : Message Counter : 1
2013-07-10 11:26:35 INFO  Producer:49 - Sent message : Message Counter : 1
2013-07-10 11:26:35 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:36 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:26:36 INFO  Producer:30 - Connection established
2013-07-10 11:26:36 INFO  Producer:47 - Sending message : Message Counter : 2
2013-07-10 11:26:36 INFO  Producer:49 - Sent message : Message Counter : 2
2013-07-10 11:26:37 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:37 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:26:37 INFO  Producer:30 - Connection established
2013-07-10 11:26:37 INFO  Producer:47 - Sending message : Message Counter : 3
2013-07-10 11:26:37 INFO  Producer:49 - Sent message : Message Counter : 3
2013-07-10 11:26:37 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:38 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:26:38 INFO  Producer:30 - Connection established
2013-07-10 11:26:38 INFO  Producer:47 - Sending message : Message Counter : 4
2013-07-10 11:26:38 INFO  Producer:49 - Sent message : Message Counter : 4
2013-07-10 11:26:39 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:39 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:26:39 INFO  Producer:30 - Connection established
2013-07-10 11:26:39 INFO  Producer:47 - Sending message : Message Counter : 5
2013-07-10 11:26:39 INFO  Producer:49 - Sent message : Message Counter : 5
2013-07-10 11:26:39 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:39 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:26:39 INFO  Producer:30 - Connection established
2013-07-10 11:26:39 INFO  Producer:47 - Sending message : Message Counter : 6
2013-07-10 11:26:39 INFO  Producer:49 - Sent message : Message Counter : 6
2013-07-10 11:26:40 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:40 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:26:40 INFO  Producer:30 - Connection established
2013-07-10 11:26:40 INFO  Producer:47 - Sending message : Message Counter : 7
2013-07-10 11:26:40 INFO  Producer:49 - Sent message : Message Counter : 7
2013-07-10 11:26:40 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:40 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:26:40 INFO  Producer:30 - Connection established
2013-07-10 11:26:40 INFO  Producer:47 - Sending message : Message Counter : 8
2013-07-10 11:26:40 INFO  Producer:49 - Sent message : Message Counter : 8
2013-07-10 11:26:41 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:41 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:26:41 INFO  Producer:30 - Connection established
2013-07-10 11:26:41 INFO  Producer:47 - Sending message : Message Counter : 9
2013-07-10 11:26:41 INFO  Producer:49 - Sent message : Message Counter : 9
2013-07-10 11:26:41 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:41 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:26:41 INFO  Producer:30 - Connection established
2013-07-10 11:26:41 INFO  Producer:47 - Sending message : Message Counter : 10
2013-07-10 11:26:41 INFO  Producer:49 - Sent message : Message Counter : 10
2013-07-10 11:26:42 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:43 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:26:43 INFO  Producer:30 - Connection established
2013-07-10 11:26:43 INFO  Producer:47 - Sending message : Message Counter : 11
2013-07-10 11:26:43 INFO  Producer:49 - Sent message : Message Counter : 11
2013-07-10 11:26:43 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:43 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:26:43 WARN  FailoverTransport:255 - Transport (tcp://127.0.0.1:61616) failed, reason:  java.net.SocketException: Software caused connection abort: recv failed, attempting to automatically reconnect
2013-07-10 11:26:50 INFO  FailoverTransport:1032 - Successfully reconnected to tcp://localhost:61626
2013-07-10 11:26:50 INFO  Producer:30 - Connection established
2013-07-10 11:26:50 INFO  Producer:47 - Sending message : Message Counter : 12
2013-07-10 11:26:50 INFO  Producer:49 - Sent message : Message Counter : 12
2013-07-10 11:26:51 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:52 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:26:52 INFO  Producer:30 - Connection established
2013-07-10 11:26:52 INFO  Producer:47 - Sending message : Message Counter : 13
2013-07-10 11:26:52 INFO  Producer:49 - Sent message : Message Counter : 13
2013-07-10 11:26:52 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:53 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:26:53 INFO  Producer:30 - Connection established
2013-07-10 11:26:53 INFO  Producer:47 - Sending message : Message Counter : 14
2013-07-10 11:26:53 INFO  Producer:49 - Sent message : Message Counter : 14
2013-07-10 11:26:54 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:54 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:26:54 INFO  Producer:30 - Connection established
2013-07-10 11:26:54 INFO  Producer:47 - Sending message : Message Counter : 15
2013-07-10 11:26:54 INFO  Producer:49 - Sent message : Message Counter : 15
2013-07-10 11:26:54 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:55 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:26:55 INFO  Producer:30 - Connection established
2013-07-10 11:26:55 INFO  Producer:47 - Sending message : Message Counter : 16
2013-07-10 11:26:55 INFO  Producer:49 - Sent message : Message Counter : 16
2013-07-10 11:26:56 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:57 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:26:57 INFO  Producer:30 - Connection established
2013-07-10 11:26:57 INFO  Producer:47 - Sending message : Message Counter : 17
2013-07-10 11:26:57 INFO  Producer:49 - Sent message : Message Counter : 17
2013-07-10 11:26:57 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:58 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:26:58 INFO  Producer:30 - Connection established
2013-07-10 11:26:58 INFO  Producer:47 - Sending message : Message Counter : 18
2013-07-10 11:26:58 INFO  Producer:49 - Sent message : Message Counter : 18
2013-07-10 11:26:59 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:59 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:26:59 INFO  Producer:30 - Connection established
2013-07-10 11:26:59 INFO  Producer:47 - Sending message : Message Counter : 19
2013-07-10 11:26:59 INFO  Producer:49 - Sent message : Message Counter : 19
2013-07-10 11:26:59 INFO  Producer:25 - Establishing connection
2013-07-10 11:26:59 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:26:59 INFO  Producer:30 - Connection established
2013-07-10 11:26:59 INFO  Producer:47 - Sending message : Message Counter : 20
2013-07-10 11:26:59 INFO  Producer:49 - Sent message : Message Counter : 20
2013-07-10 11:27:00 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:01 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:01 INFO  Producer:30 - Connection established
2013-07-10 11:27:01 INFO  Producer:47 - Sending message : Message Counter : 21
2013-07-10 11:27:01 INFO  Producer:49 - Sent message : Message Counter : 21
2013-07-10 11:27:01 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:01 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:01 INFO  Producer:30 - Connection established
2013-07-10 11:27:01 INFO  Producer:47 - Sending message : Message Counter : 22
2013-07-10 11:27:01 INFO  Producer:49 - Sent message : Message Counter : 22
2013-07-10 11:27:02 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:02 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:02 INFO  Producer:30 - Connection established
2013-07-10 11:27:02 INFO  Producer:47 - Sending message : Message Counter : 23
2013-07-10 11:27:02 INFO  Producer:49 - Sent message : Message Counter : 23
2013-07-10 11:27:02 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:02 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:02 INFO  Producer:30 - Connection established
2013-07-10 11:27:02 INFO  Producer:47 - Sending message : Message Counter : 24
2013-07-10 11:27:02 INFO  Producer:49 - Sent message : Message Counter : 24
2013-07-10 11:27:03 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:03 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:03 INFO  Producer:30 - Connection established
2013-07-10 11:27:03 INFO  Producer:47 - Sending message : Message Counter : 25
2013-07-10 11:27:03 INFO  Producer:49 - Sent message : Message Counter : 25
2013-07-10 11:27:03 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:03 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:03 INFO  Producer:30 - Connection established
2013-07-10 11:27:03 INFO  Producer:47 - Sending message : Message Counter : 26
2013-07-10 11:27:03 INFO  Producer:49 - Sent message : Message Counter : 26
2013-07-10 11:27:04 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:04 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:06 WARN  FailoverTransport:255 - Transport (tcp://127.0.0.1:61626) failed, reason:  java.net.SocketException: Software caused connection abort: recv failed, attempting to automatically reconnect
2013-07-10 11:27:15 INFO  FailoverTransport:1032 - Successfully reconnected to tcp://localhost:61616
2013-07-10 11:27:15 INFO  Producer:30 - Connection established
2013-07-10 11:27:15 INFO  Producer:47 - Sending message : Message Counter : 27
2013-07-10 11:27:15 INFO  Producer:49 - Sent message : Message Counter : 27
2013-07-10 11:27:16 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:17 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:27:17 INFO  Producer:30 - Connection established
2013-07-10 11:27:17 INFO  Producer:47 - Sending message : Message Counter : 28
2013-07-10 11:27:17 INFO  Producer:49 - Sent message : Message Counter : 28
2013-07-10 11:27:17 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:18 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:27:18 INFO  Producer:30 - Connection established
2013-07-10 11:27:18 INFO  Producer:47 - Sending message : Message Counter : 29
2013-07-10 11:27:18 INFO  Producer:49 - Sent message : Message Counter : 29
2013-07-10 11:27:19 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:20 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:27:20 INFO  Producer:30 - Connection established
2013-07-10 11:27:20 INFO  Producer:47 - Sending message : Message Counter : 30
2013-07-10 11:27:20 INFO  Producer:49 - Sent message : Message Counter : 30
2013-07-10 11:27:20 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:20 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:27:20 INFO  Producer:30 - Connection established
2013-07-10 11:27:20 INFO  Producer:47 - Sending message : Message Counter : 31
2013-07-10 11:27:20 INFO  Producer:49 - Sent message : Message Counter : 31
2013-07-10 11:27:21 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:22 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:27:22 INFO  Producer:30 - Connection established
2013-07-10 11:27:22 INFO  Producer:47 - Sending message : Message Counter : 32
2013-07-10 11:27:22 INFO  Producer:49 - Sent message : Message Counter : 32
2013-07-10 11:27:22 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:22 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:27:22 INFO  Producer:30 - Connection established
2013-07-10 11:27:22 INFO  Producer:47 - Sending message : Message Counter : 33
2013-07-10 11:27:22 INFO  Producer:49 - Sent message : Message Counter : 33
2013-07-10 11:27:23 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:23 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:27:23 INFO  Producer:30 - Connection established
2013-07-10 11:27:23 INFO  Producer:47 - Sending message : Message Counter : 34
2013-07-10 11:27:23 INFO  Producer:49 - Sent message : Message Counter : 34
2013-07-10 11:27:23 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:24 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:27:24 INFO  Producer:30 - Connection established
2013-07-10 11:27:24 INFO  Producer:47 - Sending message : Message Counter : 35
2013-07-10 11:27:24 INFO  Producer:49 - Sent message : Message Counter : 35
2013-07-10 11:27:25 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:27 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:27:27 INFO  Producer:30 - Connection established
2013-07-10 11:27:27 INFO  Producer:47 - Sending message : Message Counter : 36
2013-07-10 11:27:27 INFO  Producer:49 - Sent message : Message Counter : 36
2013-07-10 11:27:27 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:28 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:27:28 INFO  Producer:30 - Connection established
2013-07-10 11:27:28 INFO  Producer:47 - Sending message : Message Counter : 37
2013-07-10 11:27:28 INFO  Producer:49 - Sent message : Message Counter : 37
2013-07-10 11:27:29 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:30 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:27:30 INFO  Producer:30 - Connection established
2013-07-10 11:27:30 INFO  Producer:47 - Sending message : Message Counter : 38
2013-07-10 11:27:30 INFO  Producer:49 - Sent message : Message Counter : 38
2013-07-10 11:27:30 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:31 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:27:33 WARN  FailoverTransport:255 - Transport (tcp://127.0.0.1:61616) failed, reason:  java.net.SocketException: Software caused connection abort: recv failed, attempting to automatically reconnect
2013-07-10 11:27:38 INFO  FailoverTransport:1032 - Successfully reconnected to tcp://localhost:61626
2013-07-10 11:27:38 INFO  Producer:30 - Connection established
2013-07-10 11:27:38 INFO  Producer:47 - Sending message : Message Counter : 39
2013-07-10 11:27:38 INFO  Producer:49 - Sent message : Message Counter : 39
2013-07-10 11:27:39 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:39 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:39 INFO  Producer:30 - Connection established
2013-07-10 11:27:39 INFO  Producer:47 - Sending message : Message Counter : 40
2013-07-10 11:27:39 INFO  Producer:49 - Sent message : Message Counter : 40
2013-07-10 11:27:39 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:40 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:40 INFO  Producer:30 - Connection established
2013-07-10 11:27:40 INFO  Producer:47 - Sending message : Message Counter : 41
2013-07-10 11:27:40 INFO  Producer:49 - Sent message : Message Counter : 41
2013-07-10 11:27:41 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:42 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:42 INFO  Producer:30 - Connection established
2013-07-10 11:27:42 INFO  Producer:47 - Sending message : Message Counter : 42
2013-07-10 11:27:42 INFO  Producer:49 - Sent message : Message Counter : 42
2013-07-10 11:27:42 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:42 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:42 INFO  Producer:30 - Connection established
2013-07-10 11:27:42 INFO  Producer:47 - Sending message : Message Counter : 43
2013-07-10 11:27:42 INFO  Producer:49 - Sent message : Message Counter : 43
2013-07-10 11:27:43 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:44 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:44 INFO  Producer:30 - Connection established
2013-07-10 11:27:44 INFO  Producer:47 - Sending message : Message Counter : 44
2013-07-10 11:27:44 INFO  Producer:49 - Sent message : Message Counter : 44
2013-07-10 11:27:44 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:45 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:45 INFO  Producer:30 - Connection established
2013-07-10 11:27:45 INFO  Producer:47 - Sending message : Message Counter : 45
2013-07-10 11:27:45 INFO  Producer:49 - Sent message : Message Counter : 45
2013-07-10 11:27:46 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:47 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:47 INFO  Producer:30 - Connection established
2013-07-10 11:27:47 INFO  Producer:47 - Sending message : Message Counter : 46
2013-07-10 11:27:47 INFO  Producer:49 - Sent message : Message Counter : 46
2013-07-10 11:27:48 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:48 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:48 INFO  Producer:30 - Connection established
2013-07-10 11:27:48 INFO  Producer:47 - Sending message : Message Counter : 47
2013-07-10 11:27:48 INFO  Producer:49 - Sent message : Message Counter : 47
2013-07-10 11:27:48 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:49 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:49 INFO  Producer:30 - Connection established
2013-07-10 11:27:49 INFO  Producer:47 - Sending message : Message Counter : 48
2013-07-10 11:27:49 INFO  Producer:49 - Sent message : Message Counter : 48
2013-07-10 11:27:50 INFO  Producer:25 - Establishing connection
2013-07-10 11:27:51 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61626
2013-07-10 11:27:51 INFO  Producer:30 - Connection established
2013-07-10 11:27:51 INFO  Producer:47 - Sending message : Message Counter : 49
2013-07-10 11:27:51 INFO  Producer:49 - Sent message : Message Counter : 49

Here is the web console showing 50 messages enqueued.


Don't bother the #Messages Enqueued = 0 in the above screenshot. This count represents the number of messages enqueued since this node started. Since I had restarted the node after the 50 messages were already enqueued, the count shows as 0.

Now lets try to consume these messages using an asynchronous consumer using ActiveMQ connection factory with failover protocol.

Here is simple asynchronous consumer with ActiveMQConnectionFactory using failover protocol.

package com.akuntamukkala.amqms;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.log4j.Logger;

public class Consumer implements MessageListener {

	private static final Logger log = Logger.getLogger(Consumer.class);

	public static void main(String[] args) throws Exception {

		ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
				"failover:(tcp://localhost:61616,tcp://localhost:61626)");

		// Create a Connection
		Connection connection = connectionFactory.createConnection();
		connection.start();

		// Create a Session
		Session session = connection.createSession(false,
				Session.AUTO_ACKNOWLEDGE);

		// Create the destination (Topic or Queue)
		Destination destination = session.createQueue("TEST.FOO");

		// Create a MessageConsumer from the Session to the Queue
		MessageConsumer consumer = session.createConsumer(destination);
		consumer.setMessageListener(new Consumer()); // asynchronous listener
		Thread.sleep(120000); // long wait to keep program running
		consumer.close();
		session.close();
		connection.close();

	}

	/**
	 * asynchronous message listener
	 */
	public void onMessage(Message message) {
		try {
			log.info(((TextMessage) message).getText());
			Thread.sleep(500);
		} catch (JMSException e) {
			log.error(e);
		} catch (InterruptedException e) {
			log.error(e);
		}
	}

}


Here are the logs from the execution. I switched the master nodes a few times as evident in the logs.

2013-07-10 11:46:01 INFO  FailoverTransport:1030 - Successfully connected to tcp://localhost:61616
2013-07-10 11:46:01 INFO  Consumer:49 - Message Counter : 0
2013-07-10 11:46:02 INFO  Consumer:49 - Message Counter : 1
2013-07-10 11:46:02 INFO  Consumer:49 - Message Counter : 2
2013-07-10 11:46:03 INFO  Consumer:49 - Message Counter : 3
2013-07-10 11:46:03 INFO  Consumer:49 - Message Counter : 4
2013-07-10 11:46:04 INFO  Consumer:49 - Message Counter : 5
2013-07-10 11:46:04 INFO  Consumer:49 - Message Counter : 6
2013-07-10 11:46:05 INFO  Consumer:49 - Message Counter : 7
2013-07-10 11:46:05 INFO  Consumer:49 - Message Counter : 8
2013-07-10 11:46:06 INFO  Consumer:49 - Message Counter : 9
2013-07-10 11:46:06 INFO  Consumer:49 - Message Counter : 10
2013-07-10 11:46:07 INFO  Consumer:49 - Message Counter : 11
2013-07-10 11:46:07 WARN  FailoverTransport:255 - Transport (tcp://127.0.0.1:61616) failed, reason:  java.io.EOFException, attempting to automatically reconnect
2013-07-10 11:46:18 INFO  FailoverTransport:1032 - Successfully reconnected to tcp://localhost:61626
2013-07-10 11:46:18 WARN  ActiveMQMessageConsumer:1348 - Duplicate dispatch on connection: ID:AKUNTAMU-1-2141-1373474760280-1:1 to consumer: ID:AKUNTAMU-1-2141-1373474760280-1:1:1:1, ignoring (auto acking) duplicate: MessageDispatch {commandId = 0, responseRequired = false, consumerId = ID:AKUNTAMU-1-2141-1373474760280-1:1:1:1, destination = queue://TEST.FOO, message = ActiveMQTextMessage {commandId = 5, responseRequired = true, messageId = ID:AKUNTAMU-1-1739-1373473592152-1:12:1:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:AKUNTAMU-1-1739-1373473592152-1:12:1:1, destination = queue://TEST.FOO, transactionId = null, expiration = 0, timestamp = 1373473603281, arrival = 0, brokerInTime = 1373473603281, brokerOutTime = 1373474778676, correlationId = null, replyTo = null, persistent = true, type = null, priority = 4, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = null, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = true, readOnlyBody = true, droppable = false, text = Message Counter : 11}, redeliveryCounter = 0}
2013-07-10 11:46:18 INFO  Consumer:49 - Message Counter : 12
2013-07-10 11:46:19 INFO  Consumer:49 - Message Counter : 13
2013-07-10 11:46:19 INFO  Consumer:49 - Message Counter : 14
2013-07-10 11:46:20 INFO  Consumer:49 - Message Counter : 15
2013-07-10 11:46:20 INFO  Consumer:49 - Message Counter : 16
2013-07-10 11:46:21 INFO  Consumer:49 - Message Counter : 17
2013-07-10 11:46:21 INFO  Consumer:49 - Message Counter : 18
2013-07-10 11:46:22 INFO  Consumer:49 - Message Counter : 19
2013-07-10 11:46:22 INFO  Consumer:49 - Message Counter : 20
2013-07-10 11:46:23 INFO  Consumer:49 - Message Counter : 21
2013-07-10 11:46:23 INFO  Consumer:49 - Message Counter : 22
2013-07-10 11:46:24 INFO  Consumer:49 - Message Counter : 23
2013-07-10 11:46:24 INFO  Consumer:49 - Message Counter : 24
2013-07-10 11:46:25 INFO  Consumer:49 - Message Counter : 25
2013-07-10 11:46:25 INFO  Consumer:49 - Message Counter : 26
2013-07-10 11:46:26 INFO  Consumer:49 - Message Counter : 27
2013-07-10 11:46:26 INFO  Consumer:49 - Message Counter : 28
2013-07-10 11:46:27 INFO  Consumer:49 - Message Counter : 29
2013-07-10 11:46:27 INFO  Consumer:49 - Message Counter : 30
2013-07-10 11:46:28 INFO  Consumer:49 - Message Counter : 31
2013-07-10 11:46:28 INFO  Consumer:49 - Message Counter : 32
2013-07-10 11:46:29 INFO  Consumer:49 - Message Counter : 33
2013-07-10 11:46:29 INFO  Consumer:49 - Message Counter : 34
2013-07-10 11:46:30 INFO  Consumer:49 - Message Counter : 35
2013-07-10 11:46:30 INFO  Consumer:49 - Message Counter : 36
2013-07-10 11:46:31 INFO  Consumer:49 - Message Counter : 37
2013-07-10 11:46:31 INFO  Consumer:49 - Message Counter : 38
2013-07-10 11:46:32 INFO  Consumer:49 - Message Counter : 39
2013-07-10 11:46:32 WARN  FailoverTransport:255 - Transport (tcp://127.0.0.1:61626) failed, reason:  java.io.EOFException, attempting to automatically reconnect
2013-07-10 11:46:43 INFO  FailoverTransport:1032 - Successfully reconnected to tcp://localhost:61616
2013-07-10 11:46:43 WARN  ActiveMQMessageConsumer:1348 - Duplicate dispatch on connection: ID:AKUNTAMU-1-2141-1373474760280-1:1 to consumer: ID:AKUNTAMU-1-2141-1373474760280-1:1:1:1, ignoring (auto acking) duplicate: MessageDispatch {commandId = 0, responseRequired = false, consumerId = ID:AKUNTAMU-1-2141-1373474760280-1:1:1:1, destination = queue://TEST.FOO, message = ActiveMQTextMessage {commandId = 5, responseRequired = true, messageId = ID:AKUNTAMU-1-1739-1373473592152-1:40:1:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:AKUNTAMU-1-1739-1373473592152-1:40:1:1, destination = queue://TEST.FOO, transactionId = null, expiration = 0, timestamp = 1373473658595, arrival = 0, brokerInTime = 1373473658599, brokerOutTime = 1373474803745, correlationId = null, replyTo = null, persistent = true, type = null, priority = 4, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = null, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = true, readOnlyBody = true, droppable = false, text = Message Counter : 39}, redeliveryCounter = 0}
2013-07-10 11:46:43 INFO  Consumer:49 - Message Counter : 40
2013-07-10 11:46:44 INFO  Consumer:49 - Message Counter : 41
2013-07-10 11:46:44 INFO  Consumer:49 - Message Counter : 42
2013-07-10 11:46:45 INFO  Consumer:49 - Message Counter : 43
2013-07-10 11:46:45 INFO  Consumer:49 - Message Counter : 44
2013-07-10 11:46:46 INFO  Consumer:49 - Message Counter : 45
2013-07-10 11:46:46 INFO  Consumer:49 - Message Counter : 46
2013-07-10 11:46:47 INFO  Consumer:49 - Message Counter : 47
2013-07-10 11:46:47 INFO  Consumer:49 - Message Counter : 48
2013-07-10 11:46:48 INFO  Consumer:49 - Message Counter : 49

Let's check out the ActiveMQ web console:


You may find the # Messages Dequeued = 11 very interesting. This is the number of messages dequeued from the current ActiveMQ master node since it started. 

Conclusion:

We have thus seen the following in action:
  1. Run 2 ActiveMQ nodes in a Master/Slave configuration with a shared KahaDB file based database. 
  2. Configure ActiveMQ web console hosted in a Tomcat instance to point to whichever node is Master node in the cluster
  3. Failover scenario
  4. Message publisher and consumer behavior oblivious to the failover
In future blogs, I will post some other interesting ActiveMQ configurations. Stay tuned.

Happy ActiveMQ'ing!

References:

  1. http://activemq.apache.org/
  2. http://www.jakubkorab.net/category/technology/activemq


Saturday, June 29, 2013

ActiveMQ as a Windows Service using YAJSW


Objective:

This blog is to demonstrate how to run ActiveMQ JMS Broker as a Windows Service using YAJSW.

Introduction:

ActiveMQ JMS Broker(s) is a vital part of messaging infrastructure in an enterprise. In order to ensure that the ActiveMQ process stays up and running, it is best to run it as a service using a service wrapper such as Tanuki or YAJSW. Running ActiveMQ as a service helps in automatically restarting ActiveMQ process when the host machine restarts (planned or unplanned).
Service Wrapper ensures that the ActiveMQ process remains healthy. It can be configured to restart ActiveMQ process if it was to determine that the process is hung or not responding to ping. However, I must say that this is not a substitute for fixing issue(s) which actually cause ActiveMQ to hang or shut down. Service Wrapper may cure the symptom with a restart but it will not fix the root cause. It is best to troubleshoot to determine what is troubling the ActiveMQ process in order to prevent production nightmares :) Some of the common issues that I have seen relate to memory & connection leaks and inadequate capacity configuration.

Tanuki Wrapper is one the most popular open source Service Wrappers but it does not offer community edition for 64bit Windows OS as of this writing :)

Please read the Tanuki Service Wrapper release notes here:
http://wrapper.tanukisoftware.com/doc/english/download.jsp

There is a viable open source alternative in YAJSW. If you are interested in running ActiveMQ as a Windows Service on a 64bit Windows OS, you may want to consider YAJSW. There may be other alternatives but I have found YAJSW sufficient. 

Overview:

In this article, I will show how to use YAJSW to run ActiveMQ as a Windows Service. We will use ActiveMQ version 5.7.0, YAJSW version 11.03 on 64bit Windows 7 OS. Usually when you register a process to run as a service, there are additional parameters to think about such as security - which user or user groups can administer this service,  determine which interested parties receive process health status notifications, etc. In this example, we will consider a plain vanilla use case with out-of-the-box settings of ActiveMQ and YAJSW.

The actual process can be summarized in 3 easy steps. 
  1. Run YAJSW "getConfig.bat" script against a live ActiveMQ process to generate YAJSW configuration file
  2. Edit the configuration file to change a few settings
  3. Run YAJSW "installService.bat" script to register ActiveMQ process to run as a Windows Service. 
Prerequisites:
  1. Install ActiveMQ 5.7.0
  2. Install YAJSW 11.03
  3. Windows 7
  4. JDK 1.6+
Deep Dive:

Launch ActiveMQ using the default activemq.bat script


Find the process ID using jps -v


The ActiveMQ process ID is 3024

Let's generate YAJSW configuration now. We will use genConfig.bat script and pass the ActiveMQ process ID as an argument.


The generated configuration is a good start but is not good enough. We still need to edit wrapper.conf file in c:\yajsw-stable-11.03\conf directory and provide the settings listed below:

wrapper.working.dir=C:\\apache-activemq-5.7.0\\bin\\

ActiveMQ uses a runnable jar "run.jar" so we need to specify that accordingly

# Java Application main class
#wrapper.java.app.mainclass=

# or jar file
wrapper.java.app.jar=C:\\apache-activemq-5.7.0\\bin\\run.jar

# Name of the service
wrapper.ntservice.name=ActiveMQ

# Display name of the service
wrapper.ntservice.displayname=ActiveMQ-Service
# Description of the service
wrapper.ntservice.description=ActiveMQ Broker Service

# Log file to use for wrapper output logging.
wrapper.logfile=C:\\yajsw-stable-11.03\\log\\wrapper.log

Now let's install ActiveMQ as a Windows Service


Let's confirm if service got registered correctly

start -> run -> services.msc



Details:

In order to uninstall, run the uninstallService.bat


Conclusion:

We have just seen how to install ActiveMQ as a Windows Service using YAJSW on 64bit Windows. 

Sunday, June 16, 2013

Maven Release Plugin with Git, GitHub and CloudBees

Objective:

This blog is to demonstrate the use of maven release plugin using Git, GitHub and CloudBees repository. 

Introduction:

Typical software release process entails many repetitive and mundane tasks which can be automated. These tasks include building, tagging, running automated tests, generating documentation, re-versioning, deploying generated artifact(s), rollback etc. 

Maven is an opinionated software project management tool. It has a plugin architecture which facilitates automating software project lifecycle management. It provides a release-plugin which automates the software release in two steps: "prepare" and "perform" (more on this later) 

However, in most companies, software release process varies depending on technology, product and process maturity. The software release process doesn't usually lend itself to be a "one-size-fits-all" process.  That is why there is a huge debate in the community on merits and demerits of this plugin. There is a very good article by Lieven Doclo:  Why I never use the Maven release plugin. I highly suggest to read that blog & relevant comments. 

Overview:

In this article I will be sharing how to use Maven release plugin "only" for small shared components or projects where out of the box maven release plugin is sufficient. 

I will be using GitHub as SCM and CloudBees as artifact repository where release artifacts will be deployed. Both GitHub and CloudBees offer free usage tier which is just awesome! 

Here is the outline of the topics we will cover in this blog:
  1. Understand what happens in "prepare" goal
    • Release tagging
    • POM Re-versioning
    • Meta data to assist with "perform" or "rollback" goal
  2. Limitation of "rollback" goal
  3. Understand what happens in "perform" goal
  4. Browse CloudBees artifact repository to find deployed release artifact
Prerequisites:

You may find familiarity with the following useful as you read this article :)
  1. Maven
  2. Git
  3. GitHub
  4. CloudBees
  5. WebDAV (not essential but recommended)
  6. Configure SSH keys so local machine can access GitHub repository over ssh
Deep Dive:

Creating a project repository: "mrp-git-cb-demo"



Clone the remote repo from GitHub.

Ashwinis-MacBook-Pro:GIT akuntamukkala$ git clone git@github.com:akuntamukkala/mrp-git-cb-demo.git Cloning into 'mrp-git-cb-demo'...
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.

Add .gitignore file with file types which needed not be checked in and commit the changes to local and push to remote repository

Creating a sample maven project, say "Utility"using maven quickstart archetype



Ashwinis-MacBook-Pro:mrp-git-cb-demo akuntamukkala$ mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.1
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom <<<
[INFO]
[INFO] --- maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[INFO] Archetype repository missing. Using the one from [org.apache.maven.archetypes:maven-archetype-quickstart:1.1] found in catalog remote
Define value for property 'groupId': : com.app
Define value for property 'artifactId': : utility
Define value for property 'version': 1.0-SNAPSHOT: :
Define value for property 'package': com.app: :
Confirm properties configuration:
groupId: com.app
artifactId: utility
version: 1.0-SNAPSHOT
package: com.app
Y: : Y

[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.1
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.app
[INFO] Parameter: packageName, Value: com.app
[INFO] Parameter: package, Value: com.app
[INFO] Parameter: artifactId, Value: utility
[INFO] Parameter: basedir, Value: /Users/akuntamukkala/GIT/mrp-git-cb-demo
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 26.656s
[INFO] Finished at: Sun Jun 16 14:55:37 GMT+05:30 2013
[INFO] Final Memory: 9M/81M
[INFO] ------------------------------------------------------------------------

Commit the "Utility" project to GitHub

Ashwinis-MacBook-Pro:mrp-git-cb-demo akuntamukkala$ git status 
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
# .gitignore
# utility/
nothing added to commit but untracked files present (use "git add" to track)

Ashwinis-MacBook-Pro:mrp-git-cb-demo akuntamukkala$ git add .

Ashwinis-MacBook-Pro:mrp-git-cb-demo akuntamukkala$ git commit -m "first commit"
[master 8a70309] first commit
 4 files changed, 92 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 utility/pom.xml
 create mode 100644 utility/src/main/java/com/app/App.java
 create mode 100644 utility/src/test/java/com/app/AppTest.java

Ashwinis-MacBook-Pro:mrp-git-cb-demo akuntamukkala$ git push
Counting objects: 17, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (16/16), 1.63 KiB, done.
Total 16 (delta 0), reused 0 (delta 0)
To git@github.com:akuntamukkala/mrp-git-cb-demo.git
   421475b..8a70309  master -> master

The last commit is now visible in master branch at mrp-git-cb-demo repo at GitHub as shown in the following screenshot.  


Next we will make the following changes:
  1. Edit Maven's settings.xml so that Maven is aware of CloudBees release and snapshot repository credentials. 
  2. Edit Utility project's maven pom.xml to add the following:
    1. GitHub SCM configuration
    2. Distribution Management of generated artifacts
    3. Maven Release Plugin (GAV and any additional parameters)
CloudBees online Artifact Repository for release and snapshots:

When you create an account at CloudBees, you get 4 free online instances JFrog Artifact Repositories (backup, private, release, snapshot).

Please note URL of following artifact repositories:

Release:   https://repository-akuntamukkala.forge.cloudbees.com/release/
Snapshot: https://repository-akuntamukkala.forge.cloudbees.com/snapshot/

The repository access is restricted by your CloudBees account user name and password. 

In my case it is "akuntamukkala" and "canyouguess?!" respectively.

The following is a screen shot of CloudBees account showing release repository details. Please note that this repository is accessible using WebDAV. 


We need to now configure Maven installation to be aware of the CloudBees release and snapshot repository access credentials. 
Locate the settings.xml in Maven in MVN_HOME/conf directory and add the following XML snippet in the "servers" node.

    <server>
      <id>akuntamukkala-release</id>
      <username>akuntamukkala</username>
      <password>canyouguess?!</password>
    </server>
    <server>
      <id>akuntamukkala-snapshot</id>
      <username>akuntamukkala</username>
      <password>canyouguess?!</password>
    </server>


Edit Utility project's maven pom.xml to add the following XML snippet:


<!-- SCM configuration to GitHub Repo -->
<scm>
   <connection>scm:git:git@github.com:akuntamukkala/mrp-git-cb-demo.git</connection>  
   <url>scm:git:git@github.com:akuntamukkala/mrp-git-cb-demo.git</url>
   <developerConnection>scm:git:git@github.com:akuntamukkala/mrp-git-cb-demo.git</developerConnection>
   <tag>HEAD</tag>
</scm>

<!-- CloudBees Artifact Repository for release and snapshot builds -->
<!-- The repositories are accessible using WebDAV -->
<distributionManagement>
    <repository>
        <id>akuntamukkala-release</id>
        <name>Internal Release Repository</name>
        <url>dav:https://repository-akuntamukkala.forge.cloudbees.com/release</url>
    </repository>
    <snapshotRepository>
        <id>akuntamukkala-snapshot</id>
        <name>Internal Snapshot Repository</name>
        <url>dav:https://repository-akuntamukkala.forge.cloudbees.com/snapshot</url>
    </snapshotRepository>
</distributionManagement>

<!-- The maven release plugin configuration along with WebDAV extension to
help deploy the build artifacts into remote artifact repository -->

<build>
    <extensions>
         <!-- Extension required to deploy a snapshot or a release to the CloudBees
              remote maven repository using Webdav -->
         <extension>
              <groupId>org.apache.maven.wagon</groupId>
              <artifactId>wagon-webdav</artifactId>
              <version>1.0-beta-2</version>
         </extension>
    </extensions>
    <plugins>
         <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-release-plugin</artifactId>
              <version>2.4.1</version>
         </plugin>
    </plugins>
</build>

Now let's attempt to run maven release plugin's prepare goal. The prepare goal performs the following tasks:
  1. Increments project's pom.xml version
  2. Makes a release tag with pom.xml containing release version
  3. Creates meta data files such as release.properties and pom.xml.releaseBackup (useful if we need to rollback)
  4. Propagate these changes to SCM 
Let's see this in action by running the maven release plugin prepare goal.


Ashwinis-MacBook-Pro:utility akuntamukkala$ pwd

/Users/akuntamukkala/GIT/mrp-git-cb-demo/utility

Ashwinis-MacBook-Pro:utility akuntamukkala$ mvn release:prepare -DdryRun=true

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-release-plugin:2.4.1:prepare (default-cli) on project utility: Cannot prepare the release because you have local modifications :
[ERROR] [pom.xml:modified]

Oops! As you just noticed, an error occurred. This is due to the fact that there are uncommitted changes to pom.xml file. We need to ensure that there are no pending changes and all changes are pushed to GitHub repository before running maven release plugin's prepare goal . 

So let's commit all changes to the local git cloned repo and push to GitHub 

Ashwinis-MacBook-Pro:utility akuntamukkala$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: pom.xml
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# release.properties
no changes added to commit (use "git add" and/or "git commit -a")

Hmm..there is release.properties file generated by the previous execution of maven release plugin's prepare goal. We need to clean up to go back to a state prior to running prepare goal. Here is where maven release plugin's "clean" goal comes into play. 

Ashwinis-MacBook-Pro:utility akuntamukkala$ mvn release:clean
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building utility 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-release-plugin:2.4.1:clean (default-cli) @ utility ---
[INFO] Cleaning up after release...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.233s
[INFO] Finished at: Sun Jun 16 15:38:39 GMT+05:30 2013
[INFO] Final Memory: 5M/81M
[INFO] ------------------------------------------------------------------------

Now you can see that only uncommitted change is our changes to pom.xml where we added SCM, distribution management and release plugin's GAV 

Ashwinis-MacBook-Pro:utility akuntamukkala$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: pom.xml
#
no changes added to commit (use "git add" and/or "git commit -a")


Ashwinis-MacBook-Pro:utility akuntamukkala$ git add .

Ashwinis-MacBook-Pro:utility akuntamukkala$ git commit -m "scm, distribution management, release plugin config"

[master e8422bb] scm, distribution management, release plugin config

 1 file changed, 67 insertions(+), 25 deletions(-)
rewrite utility/pom.xml (83%)

Push the change to GitHub


Ashwinis-MacBook-Pro:utility akuntamukkala$ git push

Counting objects: 7, done.

Delta compression using up to 8 threads.

Compressing objects: 100% (4/4), done.

Writing objects: 100% (4/4), 1.17 KiB, done.

Total 4 (delta 1), reused 0 (delta 0)

To git@github.com:akuntamukkala/mrp-git-cb-demo.git

   8a70309..e8422bb  master -> master

Now that we have ensured that there are no more pending commits and both local and GitHub repo are in sync, let's run maven release:prepare command


Ashwinis-MacBook-Pro:utility akuntamukkala$ mvn release:prepare

[INFO] Scanning for projects...

[INFO]                                                                         

[INFO] ------------------------------------------------------------------------

[INFO] Building utility 1.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO] 

[INFO] --- maven-release-plugin:2.4.1:prepare (default-cli) @ utility ---

[INFO] Verifying that there are no local modifications...

[INFO]   ignoring changes on: **/pom.xml.backup, **/release.properties, **/pom.xml.branch, **/pom.xml.next, **/pom.xml.releaseBackup, **/pom.xml.tag

[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git status

[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility

[INFO] Checking dependencies and plugins for snapshots ...

What is the release version for "utility"? (com.app:utility) 1.0: : 

What is SCM release tag or label for "utility"? (com.app:utility) utility-1.0: : 
What is the new development version for "utility"? (com.app:utility) 1.1-SNAPSHOT: : 
[INFO] Transforming 'utility'...
[INFO] Not generating release POMs
[INFO] Executing goals 'clean verify'...
[WARNING] Maven will be executed in interactive mode, but no input stream has been configured for this MavenInvoker instance.
[INFO] [INFO] Scanning for projects...
[INFO] [INFO]                                                                         
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [INFO] Building utility 1.0
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [INFO] 
[INFO] [INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ utility ---
[INFO] [INFO] Deleting /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target
[INFO] [INFO] 
[INFO] [INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ utility ---
[INFO] [debug] execute contextualize
[INFO] [INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] [INFO] skip non existing resourceDirectory /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/src/main/resources
[INFO] [INFO] 
[INFO] [INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ utility ---
[INFO] [INFO] Compiling 1 source file to /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/classes
[INFO] [INFO] 
[INFO] [INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @ utility ---
[INFO] [debug] execute contextualize
[INFO] [INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] [INFO] skip non existing resourceDirectory /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/src/test/resources
[INFO] [INFO] 
[INFO] [INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ utility ---
[INFO] [INFO] Compiling 1 source file to /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/test-classes
[INFO] [INFO] 
[INFO] [INFO] --- maven-surefire-plugin:2.10:test (default-test) @ utility ---
[INFO] [INFO] Surefire report directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/surefire-reports
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.012 sec
[INFO] 
[INFO] Results :
[INFO] 
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] [INFO] 
[INFO] [INFO] --- maven-jar-plugin:2.3.2:jar (default-jar) @ utility ---
[INFO] [INFO] Building jar: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/utility-1.0.jar
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [INFO] BUILD SUCCESS
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [INFO] Total time: 1.755s
[INFO] [INFO] Finished at: Sun Jun 16 16:16:57 GMT+05:30 2013
[INFO] [INFO] Final Memory: 9M/81M
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] Checking in modified POMs...
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git add -- pom.xml
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git status
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git commit --verbose -F /var/folders/zs/9w9zbpnx4db89z8yrll8301r0000gn/T/maven-scm-1228315049.commit pom.xml
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git symbolic-ref HEAD
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git push git@github.com:akuntamukkala/mrp-git-cb-demo.git master:master
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Tagging release with the label utility-1.0...
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git tag -F /var/folders/zs/9w9zbpnx4db89z8yrll8301r0000gn/T/maven-scm-1142006148.commit utility-1.0
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git push git@github.com:akuntamukkala/mrp-git-cb-demo.git utility-1.0
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git ls-files
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Transforming 'utility'...
[INFO] Not removing release POMs
[INFO] Checking in modified POMs...
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git add -- pom.xml
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git status
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git commit --verbose -F /var/folders/zs/9w9zbpnx4db89z8yrll8301r0000gn/T/maven-scm-1383546415.commit pom.xml
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git symbolic-ref HEAD
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git push git@github.com:akuntamukkala/mrp-git-cb-demo.git master:master
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Release preparation complete.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 30.308s
[INFO] Finished at: Sun Jun 16 16:17:20 GMT+05:30 2013
[INFO] Final Memory: 5M/81M
[INFO] ------------------------------------------------------------------------

What just happened?

Looking at the above logs from release:prepare execution, we can see that project version has been updated to 1.1-SNAPSHOT and release pom with version 1.0 has been tagged "utility-1.0". All of these changes have been made on local repo and pushed to GitHub.

The following GitHub screenshot shows tag "utility-1.0"


Let's see pom.xml in master branch in the following screenshot. Please observe that version has been changed to 1.1-SNAPSHOT


Let's see the pom.xml in the utility-1.0 tag in the following screenshot. Please observe that release version is 1.0. This is going to be used when maven release plugin's "perform" goal is executed. More on this later.




Ashwinis-MacBook-Pro:utility akuntamukkala$ git status

# On branch master

# Your branch is ahead of 'origin/master' by 2 commits.

#

# Untracked files:

#   (use "git add <file>..." to include in what will be committed)

#

# pom.xml.releaseBackup

# release.properties

nothing added to commit but untracked files present (use "git add" to track)



Ashwinis-MacBook-Pro:utility akuntamukkala$ git pull

From github.com:akuntamukkala/mrp-git-cb-demo

   e8422bb..fda4cdd  master     -> origin/master
Already up-to-date.
Ashwinis-MacBook-Pro:utility akuntamukkala$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
# pom.xml.releaseBackup
# release.properties

Rollback after release prepare:

What if we need to rollback the changes made during "prepare" goal execution?

This could happen because of many reasons: there is always that one more bug that needs to go in this release, release gets pushed by business folks or QA reveals a critical bug etc. 

I mean we have all seen these situations at some point. So we decide to rollback using maven release plugin's rollback goal. 

This works fine...except for the fact that it does not delete the "utility-1.0" tag in the repo at least as of this writing. 

Let's see this in action...


Ashwinis-MacBook-Pro:utility akuntamukkala$ mvn release:rollback

[INFO] Scanning for projects...

[INFO]                                                                         

[INFO] ------------------------------------------------------------------------

[INFO] Building utility 1.1-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO] 

[INFO] --- maven-release-plugin:2.4.1:rollback (default-cli) @ utility ---

[INFO] Checking in modified POMs...

[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git add -- pom.xml

[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility

[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git status
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git commit --verbose -F /var/folders/zs/9w9zbpnx4db89z8yrll8301r0000gn/T/maven-scm-1207924889.commit pom.xml
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git symbolic-ref HEAD
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git push git@github.com:akuntamukkala/mrp-git-cb-demo.git master:master
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Cleaning up after release...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.952s
[INFO] Finished at: Sun Jun 16 16:42:04 GMT+05:30 2013
[INFO] Final Memory: 5M/81M
[INFO] ------------------------------------------------------------------------

Rollback reverted the changes so master branch's pom.xml contains version 1.0-SNAPSHOT. For the rollback to have executed, it is vital to have release.properties file. If that was missing, then this operation would have failed. 

Let's inspect the changes committed by rollback operation


Ashwinis-MacBook-Pro:utility akuntamukkala$ git status

# On branch master

# Your branch is ahead of 'origin/master' by 1 commit.

#

nothing to commit (working directory clean)

pom.xml in master branch reveals that version is reset to 1.0-SNAPSHOT as shown in the screenshot below. 



Here you may notice that the "utility-1.0" tag still remains in GitHub repo. 
This feature of rollback where the release tag needs to be deleted has not been implemented as of this writing. 




Let's go ahead and delete this manually for now


Ashwinis-MacBook-Pro:utility akuntamukkala$ git pull

From github.com:akuntamukkala/mrp-git-cb-demo

   fda4cdd..d280671  master     -> origin/master

Already up-to-date.

Ashwinis-MacBook-Pro:utility akuntamukkala$ git tag -n

utility-1.0     [maven-release-plugin]  copy for tag utility-1.0

Ashwinis-MacBook-Pro:utility akuntamukkala$ git tag -d utility-1.0

Deleted tag 'utility-1.0' (was d5f3fc4)
Ashwinis-MacBook-Pro:utility akuntamukkala$ git push origin :refs/tags/utility-1.0
To git@github.com:akuntamukkala/mrp-git-cb-demo.git
 - [deleted]         utility-1.0

Let's resume the release process again by first executing the prepare goal again.


Ashwinis-MacBook-Pro:utility akuntamukkala$ mvn release:prepare
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building utility 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-release-plugin:2.4.1:prepare (default-cli) @ utility ---
[INFO] Verifying that there are no local modifications...
[INFO]   ignoring changes on: **/pom.xml.backup, **/release.properties, **/pom.xml.branch, **/pom.xml.next, **/pom.xml.releaseBackup, **/pom.xml.tag
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git status
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Checking dependencies and plugins for snapshots ...
What is the release version for "utility"? (com.app:utility) 1.0: : 
What is SCM release tag or label for "utility"? (com.app:utility) utility-1.0: : 
What is the new development version for "utility"? (com.app:utility) 1.1-SNAPSHOT: : 
[INFO] Transforming 'utility'...
[INFO] Not generating release POMs
[INFO] Executing goals 'clean verify'...
[WARNING] Maven will be executed in interactive mode, but no input stream has been configured for this MavenInvoker instance.
[INFO] [INFO] Scanning for projects...
[INFO] [INFO]                                                                         
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [INFO] Building utility 1.0
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [INFO] 
[INFO] [INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ utility ---
[INFO] [INFO] Deleting /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target
[INFO] [INFO] 
[INFO] [INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ utility ---
[INFO] [debug] execute contextualize
[INFO] [INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] [INFO] skip non existing resourceDirectory /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/src/main/resources
[INFO] [INFO] 
[INFO] [INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ utility ---
[INFO] [INFO] Compiling 1 source file to /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/classes
[INFO] [INFO] 
[INFO] [INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @ utility ---
[INFO] [debug] execute contextualize
[INFO] [INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] [INFO] skip non existing resourceDirectory /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/src/test/resources
[INFO] [INFO] 
[INFO] [INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ utility ---
[INFO] [INFO] Compiling 1 source file to /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/test-classes
[INFO] [INFO] 
[INFO] [INFO] --- maven-surefire-plugin:2.10:test (default-test) @ utility ---
[INFO] [INFO] Surefire report directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/surefire-reports
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.011 sec
[INFO] 
[INFO] Results :
[INFO] 
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] [INFO] 
[INFO] [INFO] --- maven-jar-plugin:2.3.2:jar (default-jar) @ utility ---
[INFO] [INFO] Building jar: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/utility-1.0.jar
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [INFO] BUILD SUCCESS
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [INFO] Total time: 1.813s
[INFO] [INFO] Finished at: Sun Jun 16 17:40:01 GMT+05:30 2013
[INFO] [INFO] Final Memory: 9M/81M
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] Checking in modified POMs...
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git add -- pom.xml
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git status
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git commit --verbose -F /var/folders/zs/9w9zbpnx4db89z8yrll8301r0000gn/T/maven-scm-1892728079.commit pom.xml
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git symbolic-ref HEAD
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git push git@github.com:akuntamukkala/mrp-git-cb-demo.git master:master
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Tagging release with the label utility-1.0...
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git tag -F /var/folders/zs/9w9zbpnx4db89z8yrll8301r0000gn/T/maven-scm-1866393319.commit utility-1.0
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git push git@github.com:akuntamukkala/mrp-git-cb-demo.git utility-1.0
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git ls-files
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Transforming 'utility'...
[INFO] Not removing release POMs
[INFO] Checking in modified POMs...
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git add -- pom.xml
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git status
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git commit --verbose -F /var/folders/zs/9w9zbpnx4db89z8yrll8301r0000gn/T/maven-scm-347133367.commit pom.xml
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git symbolic-ref HEAD
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility && git push git@github.com:akuntamukkala/mrp-git-cb-demo.git master:master
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility
[INFO] Release preparation complete.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1:19.582s
[INFO] Finished at: Sun Jun 16 17:40:22 GMT+05:30 2013
[INFO] Final Memory: 5M/81M
[INFO] ------------------------------------------------------------------------

Now let's execute the perform goal of release plugin to see the following tasks being performed.
  1. Clone the utility-1.0 tag 
  2. Execute maven build cycle to build release artifact
  3. Upload the release artifact into CloudBees release artifact repository using WebDAV
Let's see this in action


Ashwinis-MacBook-Pro:utility akuntamukkala$ mvn release:perform

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building utility 1.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-release-plugin:2.4.1:perform (default-cli) @ utility ---
[INFO] Checking out the project to perform the release ...
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target && git clone --branch utility-1.0 git@github.com:akuntamukkala/mrp-git-cb-demo.git /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target
[INFO] Executing: /bin/sh -c cd /var/folders/zs/9w9zbpnx4db89z8yrll8301r0000gn/T/ && git ls-remote git@github.com:akuntamukkala/mrp-git-cb-demo.git
[INFO] Working directory: /var/folders/zs/9w9zbpnx4db89z8yrll8301r0000gn/T
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout && git fetch git@github.com:akuntamukkala/mrp-git-cb-demo.git
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout && git checkout utility-1.0
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout
[INFO] Executing: /bin/sh -c cd /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout && git ls-files
[INFO] Working directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout
[INFO] Invoking perform goals in directory /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility
[INFO] Executing goals 'deploy'...
[WARNING] Maven will be executed in interactive mode, but no input stream has been configured for this MavenInvoker instance.
[INFO] [INFO] Scanning for projects...
[INFO] [WARNING] 
[INFO] [WARNING] Some problems were encountered while building the effective model for com.app:utility:jar:1.0
[INFO] [WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-javadoc-plugin is missing.
[INFO] [WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-deploy-plugin is missing.
[INFO] [WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-source-plugin is missing.
[INFO] [WARNING] 
[INFO] [WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[INFO] [WARNING] 
[INFO] [WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[INFO] [WARNING] 
[INFO] [INFO]                                                                         
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [INFO] Building utility 1.0
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [INFO] 
[INFO] [INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ utility ---
[INFO] [debug] execute contextualize
[INFO] [INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] [INFO] skip non existing resourceDirectory /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/src/main/resources
[INFO] [INFO] 
[INFO] [INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ utility ---
[INFO] [INFO] Compiling 1 source file to /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/classes
[INFO] [INFO] 
[INFO] [INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @ utility ---
[INFO] [debug] execute contextualize
[INFO] [INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] [INFO] skip non existing resourceDirectory /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/src/test/resources
[INFO] [INFO] 
[INFO] [INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ utility ---
[INFO] [INFO] Compiling 1 source file to /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/test-classes
[INFO] [INFO] 
[INFO] [INFO] --- maven-surefire-plugin:2.10:test (default-test) @ utility ---
[INFO] [INFO] Surefire report directory: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/surefire-reports
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.012 sec
[INFO] 
[INFO] Results :
[INFO] 
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] [INFO] 
[INFO] [INFO] --- maven-jar-plugin:2.3.2:jar (default-jar) @ utility ---
[INFO] [INFO] Building jar: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/utility-1.0.jar
[INFO] [INFO] 
[INFO] [INFO] >>> maven-source-plugin:2.2.1:jar (attach-sources) @ utility >>>
[INFO] [INFO] 
[INFO] [INFO] <<< maven-source-plugin:2.2.1:jar (attach-sources) @ utility <<<
[INFO] [INFO] 
[INFO] [INFO] --- maven-source-plugin:2.2.1:jar (attach-sources) @ utility ---
[INFO] [INFO] Building jar: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/utility-1.0-sources.jar
[INFO] [INFO] 
[INFO] [INFO] --- maven-javadoc-plugin:2.9:jar (attach-javadocs) @ utility ---
[INFO] [INFO] 
[INFO] Loading source files for package com.app...
[INFO] Constructing Javadoc information...
[INFO] Standard Doclet version 1.6.0_45
[INFO] Building tree for all the packages and classes...
[INFO] Generating /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/apidocs/com/app//App.html...
[INFO] Generating /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/apidocs/com/app//package-frame.html...
[INFO] Generating /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/apidocs/com/app//package-summary.html...
[INFO] Generating /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/apidocs/com/app//package-tree.html...
[INFO] Generating /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/apidocs/constant-values.html...
[INFO] Generating /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/apidocs/com/app//class-use/App.html...
[INFO] Generating /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/apidocs/com/app//package-use.html...
[INFO] Building index for all the packages and classes...
[INFO] Generating /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/apidocs/overview-tree.html...
[INFO] Generating /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/apidocs/index-all.html...
[INFO] Generating /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/apidocs/deprecated-list.html...
[INFO] Building index for all classes...
[INFO] Generating /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/apidocs/allclasses-frame.html...
[INFO] Generating /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/apidocs/allclasses-noframe.html...
[INFO] Generating /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/apidocs/index.html...
[INFO] Generating /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/apidocs/help-doc.html...
[INFO] Generating /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/apidocs/stylesheet.css...
[INFO] [INFO] Building jar: /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/utility-1.0-javadoc.jar
[INFO] [INFO] 
[INFO] [INFO] --- maven-install-plugin:2.3.1:install (default-install) @ utility ---
[INFO] [INFO] Installing /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/utility-1.0.jar to /Users/akuntamukkala/.m2/repository/com/app/utility/1.0/utility-1.0.jar
[INFO] [INFO] Installing /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/pom.xml to /Users/akuntamukkala/.m2/repository/com/app/utility/1.0/utility-1.0.pom
[INFO] [INFO] Installing /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/utility-1.0-sources.jar to /Users/akuntamukkala/.m2/repository/com/app/utility/1.0/utility-1.0-sources.jar
[INFO] [INFO] Installing /Users/akuntamukkala/GIT/mrp-git-cb-demo/utility/target/checkout/utility/target/utility-1.0-javadoc.jar to /Users/akuntamukkala/.m2/repository/com/app/utility/1.0/utility-1.0-javadoc.jar
[INFO] [INFO] 
[INFO] [INFO] --- maven-deploy-plugin:2.7:deploy (default-deploy) @ utility ---
[INFO] WAGON_VERSION: 1.0-beta-2
[INFO] Uploading: dav:https://repository-akuntamukkala.forge.cloudbees.com/release/com/app/utility/1.0/utility-1.0.jar
[INFO] 3 KB   
[INFO]        
[INFO] Uploaded: dav:https://repository-akuntamukkala.forge.cloudbees.com/release/com/app/utility/1.0/utility-1.0.jar (3 KB at 0.2 KB/sec)
[INFO] Uploading: https://repository-akuntamukkala.forge.cloudbees.com/release/com/app/utility/1.0/utility-1.0.pom
[INFO] 3 KB   
[INFO]        
[INFO] Uploaded: https://repository-akuntamukkala.forge.cloudbees.com/release/com/app/utility/1.0/utility-1.0.pom (3 KB at 0.3 KB/sec)
[INFO] Downloading: https://repository-akuntamukkala.forge.cloudbees.com/release/com/app/utility/maven-metadata.xml
[INFO]        
[INFO] Uploading: https://repository-akuntamukkala.forge.cloudbees.com/release/com/app/utility/maven-metadata.xml
[INFO] 290 B   
[INFO]         
[INFO] Uploaded: https://repository-akuntamukkala.forge.cloudbees.com/release/com/app/utility/maven-metadata.xml (290 B at 0.1 KB/sec)
[INFO] Uploading: dav:https://repository-akuntamukkala.forge.cloudbees.com/release/com/app/utility/1.0/utility-1.0-sources.jar
[INFO] 761 B   
[INFO]         
[INFO] Uploaded: dav:https://repository-akuntamukkala.forge.cloudbees.com/release/com/app/utility/1.0/utility-1.0-sources.jar (761 B at 0.1 KB/sec)
[INFO] Uploading: dav:https://repository-akuntamukkala.forge.cloudbees.com/release/com/app/utility/1.0/utility-1.0-javadoc.jar
[INFO] 4 KB    
[INFO] 8 KB   
[INFO] 12 KB   
[INFO] 16 KB   
[INFO] 20 KB   
[INFO] 21 KB   
[INFO]         
[INFO] Uploaded: dav:https://repository-akuntamukkala.forge.cloudbees.com/release/com/app/utility/1.0/utility-1.0-javadoc.jar (21 KB at 2.5 KB/sec)
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [INFO] BUILD SUCCESS
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [INFO] Total time: 42.872s
[INFO] [INFO] Finished at: Sun Jun 16 17:58:53 GMT+05:30 2013
[INFO] [INFO] Final Memory: 16M/81M
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] Cleaning up after release...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1:03.465s
[INFO] Finished at: Sun Jun 16 17:58:53 GMT+05:30 2013
[INFO] Final Memory: 5M/81M
[INFO] ------------------------------------------------------------------------

Viewing the remote repository using a WebDAV client:

Download and configure CyberDuck WebDAV Client to browse the CloudBees release artifact repository. Use the same credentials which we used in settings.xml



The following screenshot shows the contents on release artifact repository. 


Conclusion:

We have seen how to use maven release plugin's prepare and perform goals in a project using Git, GitHub and CloudBees JFrog Artifact Repository. 

Maven release plugin is feature rich and there are so many options that I haven't discovered . For most part we have seen the plain vanilla use case here. 

I'd love to hear about your use cases where you found maven release plugin useful and where you did not. 

As always, any comments, suggestions to improve content are most welcome. 

Thanks again for your interest! Long live open source!

Useful References:
  1. http://maven.apache.org/maven-release/maven-release-plugin/index.html
  2. http://www.insaneprogramming.be/?p=362
  3. https://github.com/arey/maven-config-github-cloudbees/blob/master/pom.xml