Friday, October 12, 2012

ActiveMQ Composite Destinations


ActiveMQ Composite Destinations

Composite queue allows one-to-many relationship. Send a message to One Queue (A) and it will forward the message to Queue B, Queue C and Topic D.
To map Composite destination you need to add following section in virtualDestinations tag.
 <destinationInterceptors>
    <virtualDestinationInterceptor>
        <virtualDestinations>
<compositeQueue name="TEST.QUEUE.A">
   <forwardTo>
<queue physicalName="TEST.QUEUE.B" />
<queue physicalName="TEST.QUEUE.C" />
<queue physicalName="TEST.TOPIC.D" />
   </forwardTo>
</compositeQueue>
        </virtualDestinations>
    </virtualDestinationInterceptor>
  </destinationInterceptors>

By default, subscribers cannot consume messages directly from a composite queue or topic - it is a logical construct only. Given the configuration above, subscribers can only consume messages from TEST.QUEUE.B, TEST.QUEUE.C and TEST.TOPIC.D; but NOT TEST.QUEUE.A.

Using filtered destinations

You may wish to create a virtual destination which forwards messages to multiple destinations but applying a selector first to decide if the message really does have to go to a particular destination.
 <destinationInterceptors>
    <virtualDestinationInterceptor>
        <virtualDestinations>
<compositeQueue name="TEST.QUEUE.A">
   <forwardTo>
<filteredDestination selector="criteria = ‘B’” queue="TEST.QUEUE.B" />
<filteredDestination selector="criteria = ‘C’” queue="TEST.QUEUE.C" />
<filteredDestination selector="criteria = ‘D’” queue="TEST.TOPIC.D" />
   </forwardTo>
</compositeQueue>
        </virtualDestinations>
    </virtualDestinationInterceptor>
  </destinationInterceptors>

In the case above, message from TEST.QUEUE.A will be forwarded to filtered destinations with selector criteria. Result is same as having selector based consumer on TEST.QUEUE.B


Important Aspects of Composite Destinations:

-          Listener Queues (under forwardTo Tag) will not be created automatically. If queues are not present, message will be LOST.
-          If you want to store message in composite queue, make forwardOnly flag as ‘false’. It’s true by default.
<compositeQueue name="TEST.QUEUE.A" forwardOnly="false">   
      <forwardTo>
<queue physicalName="TEST.QUEUE.B" />
   </forwardTo>
</compositeQueue>

-          Composite queue can send the message to Virtual Topic, which will be further consumed by multiple Virtual Destinations.
-          Virtual Topic Selector Aware Consumers will not pull the message if consumer is not active; On the contrary, Filtered Composite destinations pull the message despite of consumer’s active status. This is very helpful in real world scenarios.
-          Important: Composite Destinations Supports wildcards. This is also valid for Filtered Destinations.
<destinationInterceptors>
   <virtualDestinationInterceptor>
      <virtualDestinations>
<compositeQueue name="TEST.QUEUE.A">
<forwardTo>
   <filteredDestination selector="criteria = ‘B’” queue="TEST.B.>."/>
   <queue physicalName="COMPOSITE.WILD.>."/>
</forwardTo>
</compositeQueue>
</virtualDestinations>
</virtualDestinationInterceptor>
</destinationInterceptors>

In the settings above, message will be forwarded to all the queues starting with “COMPOSITE.WILD”. Also, the message with filtered destinations will be forwarded to all the queues starting with ‘TEST.B’.

Thursday, August 30, 2012

WTX with ActiveMQ Using JMS Adapter


WebSphere Transformation Extender's interaction with Activemq. Not hard but little tricks are important. As usual, if you google this solution, you will not find a single site or blog stating exact steps. So, here it is. Post your comments for questions.

Step 1: Setting jndi.propertise

Place provided “jndi.properties” file in <WTX_INSTALL>/java/lib directory or defined CLASSPATH. Sample jndi.properties can be downloaded from here.

Step 2: Include Jars

Include following Jars in local accessible folder.
activemq-all-5.5.1-fuse-07-11.jar
geronimo-jms_1.1_spec-1.1.1.jar
log4j-1.2.16.jar
slf4j-api-1.6.4.jar
slf4j-log4j12-1.6.4.jar
spring-jms-3.0.6.RELEASE.jar

Step 3: Add External Jars in dtx.ini


Include above mentioned jars in External jar section dtx.ini file. (replace home/aad/tmp with your folder path from root)
jar1=/home/aad/tmp/activemq-all-5.5.1-fuse-07-11.jar
jar2=/ home / aad /tmp/geronimo-jms_1.1_spec-1.1.1.jar
jar3=/ home / aad /tmp/log4j-1.2.16.jar
jar4=/ home / aad /tmp/slf4j-api-1.6.4.jar
jar5=/ home / aad /tmp/slf4j-log4j12-1.6.4.jar
jar6=/ home / aad /tmp/spring-jms-3.0.6.RELEASE.jar

Step 4: Command

-T -HDR -ICTXFURL tcp://<brokerURL>:<port>
 -ICTXF org.apache.activemq.jndi.ActiveMQInitialContextFactory
-CFN "connectionFactory"
-QN " testQueue"
Where
connectionFactory – JNDI Connection Factory Name
testQueue – JNDI Queue Name

Wednesday, August 8, 2012

WebSphere MQ With Tomcat : JNDI Property Names


WebSphere MQ JNDI Property Names:

I searched across the web and I didn’t find a single site stating exact JNDI MQ option for setting SSLCipherSuite value. I made this entire list of properties which can be useful for providing wide range of options to MQConnectionFactoty.
WebSphere MQ (IBM MQ) has lot of properties which can be made available from JNDI (Context.XML) entries. IBM MQ uses very specific Names which need to be set in Context XML Resource Entry.
Sample Resource Entry in Context is as below:
<Resource
        CHAN="<Channel Name>"
        HOST="<HostName>"
        PORT="<portNumber>"
        QMGR="<queueManagerName>"
        .
        .
        auth="Container"
       description="MQ JMS Queue Connection Factory"
        factory="com.ibm.mq.jms.MQQueueConnectionFactoryFactory"
        name="jms/ConnectionFactory"
        type="com.ibm.mq.jms.MQQueueConnectionFactory"/>

Below is the list of properties and their meaning.
Property Name
Used For
Short Description
CHAN
Channel Name
1 through 20 ASCII characters
HOST
Host Name
A valid TCP/IP host name
PORT
Port Number
A valid TCP/IP port numbe
QMGR
Queue Manager Name
Queue Manager Name
VER
Version
String
DESC
Description
String
TRAN
Transport Type
BINDINGS, CLIENT, DIRECT, QUEUED
CID
Client ID
JMS client identifier
CCS
CCS ID
coded character set identifier
MNS
Map Style Name
String
RCX
Receive Exit
String
RCXI
Receive Exit Init
String
SCX
Security Exit
String
SCXI
Security Exit Init
String
SDX
Send Exit
String
SDXI
Send Exit Init
String
SCPHS
SSL Cipher Suite  value
Cipher suite to use for SSL connection
SPEER
SSL Peer Name
Distinguished name is used to check the identifying certificate presented by the server at connection time
SCRL
SSL Certificate Store
 list of zero or more Certificate Revocation List
HC
HDR Component list
String
MC
Message Comp list
String
CT
Connection Tag
String
CTO
Connection Options
String
SCC
Send Check Count
String
SCALD
Shared Conversation Allowed
String
SRC
SSL Reset Count
String
SFIPS
SSL Fips Required
String
SPAG
Synch Points All Gets
String
UCP
Use Connection Pooling
Optional set of connection pool settings
PINT
Polling Interval
The interval, in milliseconds, between scans of all receivers during asynchronous message delivery
PVER
Provider Version
String
WCFMT
Wild Card Format
String
MBS
Message Batch Size
String
FIQ
Fail If Quiesce
Whether applications return from a method call if the queue manager has entered a controlled failure.
LA
Local Address
Specifies the local server address
RINT
Rescan Interval
the interval in milliseconds between which a topic is scanned to look for messages that have been added to a topic out of order
TCM
Target Client Matching
String
AEX
Asynch Exception
String
CCDTRUL
CCDT URL
String

These properties are very useful while using websphere MQ with Tomcat. This will enable user to get rid of provider specific code in App.
This list doesn’t end here. I will add more properties, as and when I get to know them, I will also add the descriptions as I find them.
More questions? Post a comment. I will try to answer as soon as possible.

Tuesday, August 7, 2012

ActiveMQ Mirror Queue: Working Example.


If you reached here, you might have already checked few very confusing paragraphs about Mirror queues in ActiveMQ.
Mirror Queues are disabled by default. To enable them, you have to following settings in activemq.xml
<destinationInterceptors>
<mirroredQueue copyMessage = "true" postfix="" prefix="MIRROR."/>
                <virtualDestinationInterceptor>
                                <virtualDestinations>
                                                <virtualTopic name="MIRROR.TEST.>"  prefix="MIR.>." selectorAware="false"/>
                                </virtualDestinations>
                </virtualDestinationInterceptor>
</destinationInterceptors>
               
Out of above: “<mirroredQueue copyMessage = "true" postfix="" prefix="MIRROR."/>” is actually responsible for enabling Mirror Queues.

How ActiveMQ Handles Mirror Queues:

1.       When you enable Mirror Queues, with say prefix as “MIRROR.”, for every queue in the broker one Topic will be created with MIRROR. Prefix.
2.       Now to receive a message from this Topic, Virtual Destinations can be used. More about Virtual Destination can be found here.

Working Example:

                Let’s consider above configuration for prefix for Mirror queues and Virtual Destinations.
1.       Create a queue: TEST.QUEUE
2.       With above settings, Mirror Topic is automatically created as : MIRROR.TEST.QUEUE
3.       Create Virtual Topic Consumer : MIR.COPY.MIRROR.TEST.QUEUE
a.       MIR – Defined Virtual Topic Interceptor
b.      COPY – Name of the Consumer
c.       MIRROR.TEST.QUEUE – is a Topic Name
4.       Send a test message to TEST.QUEUE, same message will appear in MIR.COPY.MIRROR.TEST.QUEUE.

This is complete setting of Mirror Queues.

Problems:

1.       Mirror Topics will be created for Every Queue in the broker
2.       As broker has to track each message from the queue and copy it to topic, further to virtual destination, broker may face performance problem depending on load.

Friday, July 27, 2012

QueueSender or MessageProducer? Which one I should choose?


QueueSender or MessageProducer?

Well the answer is: - MessageProducer. There is nothing new in QueueSender or TopicPublisher which is not available in MessageProducer. But converse is true. MessageProducer has few more features than QueueSender and TopicPublisher. Creating a MessageProducer provides the same features as creating a TopicPublisher. or QueueSender.

Also, there is an added benefit, if your code is sending messages to Queue as well as a Topic, you can dynamically pass destination to your MessageProducer creator and make the code consistent.

This analogy can be used with QueueSession and TopicSession objects. Using a generic Session is always recommended.

But don’t be panic if you have existing code with QueueSender and QueueReceiver, for futher development though, please use their parents J

Did you still have a doubt? Post a comment. I will try to answer it as soon as possible.


Friday, July 20, 2012

Converting CSV to XML With Camel Bindy


Converting CSV file to XML using Apache Camel.


Why Apache Camel?
Because Camel Rocks :). Camel has huge transformation libraries which makes code easier and simple to understand and execute. Also Camel is free. It’s an open-source tool with huge user base and nice support. 

What’s the Corporate Problem?
Converting CSV to XML is common problem across IT industry where CSV might be the input imported by user and Web-Service might be expecting XML formatted data to run the business logic. Here we will do this conversion in two steps, and both the steps are useful for applicable applications.
Step 1. Converting CSV file to POJO objects (Beans)
Step 2. Converting POJO list to XML using xstream (Open Source easy to use Jar file)
If you are just interested in POJO list, please stop at first step.

Can you run through any example?

Sure thing. Let’s consider we have Employee.csv file having data like below.
employeeId,firstName,lastName,role
23445,Ambarish,Deshpande,Java Lead
23411,Paul,Bulson,Team Member

First we need a bean (DTO) class to map CSV fields. Getters / Setters are optional here.

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@CsvRecord(separator = ",", skipFirstLine = true)
public class EmployeeDTO implements Serializable{
@XmlAttribute
      @DataField(pos = 1)
      private int employeeId;
      @XmlAttribute
      @DataField(pos = 2)
      private String firstName;
      @XmlAttribute
      @DataField(pos = 3)
      private String lastName;
      @XmlAttribute
      @DataField(pos = 4)
      private String role;
}

Annotations?

All @XML* annotations are coming from javax.xml.bind.annotation.* package.
For @CSVRecord and @DataField you have import camel-bindy.jar. I have listed all the dependencies in Appendix section at last.

Now, for actual conversion, camel route must be created.

public class ConvertorRoute implements RoutesBuilder{
     
@Override
public void addRoutesToCamelContext(CamelContext context) throws Exception {
  context.addRoutes(new RouteBuilder() {
public void configure() {
  try {
            DataFormat bindy = new BindyCsvDataFormat("com.package.dto");
                  from("file://TEST?fileName=Employee.csv").
                  unmarshal(bindy).
                  marshal().
                  xstream().
                  to("file://TESTOUT?fileName=employee.xml");
            } catch (Exception e) {
                        e.printStackTrace();
            }
         }
     });
}

public static void main(String[] args) { 
 try{
CamelContext context = new DefaultCamelContext();
      ConvertorRoute route = new ConvertorRoute();
      route.addRoutesToCamelContext(context);
      context.start();
      Thread.sleep(5000);
      context.stop();
  }catch(Exception exe){
      exe.printStackTrace();
}

}

Steps in Route:

1.    Register Bean package (where DTO class resides) with BindyCSVDataFormat.

    DataFormat bindy = new BindyCsvDataFormat("com.package.dto");

2.    Pick Up the file from TEST folder. (Root//TEST)
3.    Unmarshal the csv file with register Bindy. This step creates a List of EmployeeDTO. If intended output is achieved here. Please use this output further.
4.    Marshal().xstream() will convert this DTO List to XML and finally
5.    Output file will be written on TESTOUT folder as employee.xml file.


Employee.XML file:             


<?xml version="1.0" ?>
<list>
<map>
<entry>
  <string>com.thd.eai.dto.EmployeeDTO</string>
<com.thd.eai.dto.EmployeeDTO>
      <employeeId>23445</employeeId>
    <firstName>Ambarish</firstName>
      <lastName>Deshpande</lastName>
      <role>Lead Java</role>
   </com.thd.eai.dto.EmployeeDTO>
  </entry>
 </map>
<map>
 <entry>
  <string>com.thd.eai.dto.EmployeeDTO</string>
<com.thd.eai.dto.EmployeeDTO>
      <employeeId>23411</employeeId>
      <firstName>Paul</firstName>
      <lastName>Bulson</lastName>
      <role>Team Member</role>
   </com.thd.eai.dto.EmployeeDTO>
 </entry>
</map>
</list>



Appendix and References:

List of dependencies: 

camel-bindy-2.9.0.jar,
camel-core-2.9.0.jar,
camel-csv-2.9.0.jar,
camel-xstream-2.9.0.jar, 
slf4j-api-1.6.4.jar,
slf4j-log4j12-1.6.4.jar,
solr-commons-csv-1.3.0.jar,
xstream-1.3.1 

Important Links: