Tutorial - BMC Atrium Orchestrator JMS Monitor Adapter with Apache ActiveMQ

Version 1
    Share:|

    JMS Monitor Adapter Tutorial Using Apache ActiveMQ

     

    This tutorial steps you through using the BMC Atrium Orchestrator (BAO) JMS adapter with the Apache ActiveMQ application.  It uses ActiveMQ's sample "Market Data Publisher" broker, and shows how BAO can subscribe to the JMS message queue, watch for specific topic messages (stock prices), and take a specific action (writing stock prices to a text file).


    Note that some of these steps are already taken care of for you by BAO's installation of the base adapters, but it's a good idea to verify everything is in place.


    As a reminder, there are 4 main components used in BAO monitoring:

    • The Monitor Adapter
    • The Adapter Event
    • The Rules
    • The Process (Workflow)

     

     

    The Monitor Adapter defines the JMS client subscription and watches for messages on the desired topic.  When the Monitor Adapter picks up a message, it hands it off to the Adapter Manager, which automatically creates the Monitor Event.  Rules defined in the Module watch for specific Monitor Events and - if the criteria is a match - passes it along to the workflow Process.

     

    These components are all managed using XML (behind the scenes), and all "talk" to one-another.  This tutorial will touch on all of these areas, and includes the following sections:

     

      1. Client Setup - Copy the ActiveMQ client JAR files to the BMC Atrium Orchestrator peers on which the JMS monitor and actor adapters are enabled. (Adapter prerequisite).
      2. Adapter Configuration(s) - Monitor Adapter
      3. Adapter Operation Verification - Start ActiveMQ, Begin Publishing & Logging (Adapter Event)
      4. Workflow - Process & Rules

    NOTE:  You'll be working with XML at almost every stage of this tutorial.  Make sure that you're up to speed with XML and XPath transformations.  If not (or it's been a while) stop right now and spend an hour at W3Schools:


    XML - http://www.w3schools.com/xml/default.asp

    XPath - http://www.w3schools.com/xpath/default.asp


    ...You'll thank me later.

    This example assumes you'll be running both the ActiveMQ broker, and BAO on the same server (localhost).


    I) Client Setup - ActiveMQ Client JAR Files

     

    First, check to see what's installed on your BMC Atrium Orchestrator peer server by looking in the following directory:

    AO_HOME\tomcat\webapps\baocdp\WEB-INF\lib


    Usually this is something like: "C:\Program Files\BMC Software\CDP\tomcat\webapps\baocdp\WEB-INF\lib"

    You're looking for the following .jar files (actual version numbers may differ):

    activemq-all-5.4.2.jar

    activemq-core-5.4.2.jar

    spring-2.5.4.jar

    spring-core-2.5.4.jar

    spring-jms-2.5.4.jar

    If you have these files (there may be others) you should be good.  If not, download & extract ActiveMQ from here:

    http://activemq.apache.org/download.html

     

    Copy the .jar files from the extracted location to your BMC Atrium Orchestrator to your peer-enabled computer and the location specified above.

    NOTE: You'll want to install ActiveMQ locally anyway, since the sample stock portfolio messaging broker is included. 

    II) Adapter Configuration - Monitor Adapter
    The BAO JMS monitor base adapter configuration is documented here:

     

    Our tutorial makes use of the example "Market Data Publisher" included with ActiveMQ.  The Market Data Publisher publishes mock stock market quotes for 4 stock symbols: IBMW, MSFT, BEAS, and SUNW, each as their own JMS topic.  For our example we'll be subscribing to the Microsoft topic (MSFT).

    NOTE: If your publishing model is peer-to-peer (PTP), then you'll be using <queues> as documented in the BMC documentation.  However, most people use the Publish/Subscribe model so we use <topics> only.

    XML Sample of Apache ActiveMQ JMS Monitor Adapter Configuration:
    <config>

    <jndi>

      <java.naming.factory.initial>org.apache.activemq.jndi.ActiveMQInitialContextFactory

      </java.naming.factory.initial>

      <java.naming.provider.url>tcp://127.0.0.1:61616

      </java.naming.provider.url>

    </jndi>

      <connection-factory>ConnectionFactory</connection-factory>

      <number-of-retries>3</number-of-retries>

      <retry-wait>2000</retry-wait>

      <topics>

        <topic>

          <destination-context-name>dynamicTopics/STOCKS.MSFT

          </destination-context-name>

          <message-class>com.realops.adapter.jms.message.GenericMessageProcessor

          </message-class>

        </topic>

      </topics>

    </config>


    I've named this monitor adapter: "RO_Adapter_JMS_Localhost" (make note, it'll show up later on...).

     

    BREAK IT DOWN

     

    <config> - The config tags wrap the entire XML configuration and are required.


    <jndi> - The first of the required XML tags for BAO.  Actually having elements defined within these tags is optional, but the tags themselves are required.  Typically there are at least 2 elements configured here: <java.naming.factory.initial> & <java.naming.provider.url>.

     

    <java.naming.factory.initial> - Used to define the initial context class of ActiveMQ.  This will always be:

     

    org.apache.activemq.jndi.ActiveMQInitialContextFactory


    <java.naming.provider.url> - The protocol, hostname, and port  of the ActiveMQ message broker.  The protocol is typically "tcp", but if  you're using an embedded broker, then you may use "vm" (not tested).


    The hostname & port follow the normal URL formatting  conventions, and can be "localhost", an IP address, a host name, or a  fully-qualified domain name.  The default port for accessing an ActiveMQ  broker is 61616.

    NOTE: The ActiveMQ JNDI Support page also includes a third attribute, "topic.MyTopic" which isn't used by BAO.  The topic will be defined further down in the <topics> section, outside of <jdni>.

    That's all that's required for the <jndi> section.

    <connection-factory>- The second of the 2 required XML tags within BAO.  If you were building your own ActiveMQ client application you could specify a connection factory name within a jndi.properties files. But for BAO it must be:

    ConnectionFactory

    NOTE: This is case-sensitive, and a lower-case "c" will not work (e.g.; connectionFactory).  This is somewhat misleading in that a lot of generic ActiveMQ documentation, including the jndi.properties information linked above, show how multiple values can respond to the <connection-factory> tag.  But our testing has shown that the only reliable string to use is "ConnectionFactory".

    <topics> - If your topic is dynamically generated, then <destination-context-name> must include the prefix:

    dynamicTopics/

     

    You can configured multiple topics for a single adapter by using the <topic> tag inside of <topics>, each with their own <destination-context-name>.

     

    Save your adapter, and remember to activate it on the grid.

     

    III) Adapter Operation Verification - Start ActiveMQ, Begin Publishing & Logging


    3.1) Start ActiveMQ - Per ApacheMQ instructions.  From the command prompt (cmd):

     

    C:\apache-activemq-5.4.2>bin\activemq


    3.2) Begin Publishing Market Portfolio Data - Navigate to the localhost web server and the sample data page.  Click the link to begin publishing.

     

    http://localhost:8161/demo/portfolioPublish?count=1&refresh=2&stocks=IBMW&stocks=BEAS&stocks=MSFT&stocks=SUNW


    3.3) Logging


    The best way to verify the monitor log is working properly is using DEBUG level logging of the Adapter. Enable Adapter DEBUG level logging in the Peer Manager of BAO CDP.


    Additionally, this is also one of surest ways to determine what your incoming XML response is from the JMS broker (the only way, actually).  Knowing this XML is important because in most cases you'll be building Rules using the BAO Development Studio and these rules will be looking at specific element tags and their values.


    Successful responses to JMS Monitor log look like this (grid.log):

    19 Jun 2012 08:27:35,895 INFO  JMSMonitorAdapter : Sending event to adapter manager : <message>

      <destination>dynamicTopics/STOCKS.MSFT

          </destination>

      <header>

        <JMSDeliveryMode>1</JMSDeliveryMode>

        <JMSExpiration>0</JMSExpiration>

        <JMSPriority>4</JMSPriority>

        <JMSMessageID>ID:localhost-1903-1340119365529-3:1:1:1:77</JMSMessageID>

        <JMSTimestamp>1340119660654</JMSTimestamp>

        <JMSCorrelationID />

        <JMSType />

        <JMSRedelivered>false</JMSRedelivered>

        <character-set>ISO-8859-2</character-set>

        <JMSReplyTo />

      </header>

      <body>

        <text>

          <price stock="MSFT" bid="61.93585791746035" offer="61.99779377537781" movement="down" />

        </text>

      </body>

    </message>

    When you see this information in your log it's confirmation that your adapter has been configured properly and BAO is receiving messages for the subscribed topic.

     

    MONITOR ADAPTER EVENT SAMPLE XML

     

    Once the monitor adapter sends the message to the adapter manager, an "adapter event" is created.  These events wrap your message with additional XML as described in the Monitor Adapter Events documentation.

    NOTE:  The elements defined within the adapter event are what your workflow rules (below) will use as their criteria to run the process within your workflow.

    Successful Adapter Events will look like this in the grid.log.  But they won't be formatted on separate lines, which makes them tricky to spot (use "Find" in your log viewer):

    <adapter-event>
          <source-adapter>RO_Adapter_JMS_Localhost</source-adapter>
          <event>jms message received event</event>
          <data>
               <message>

                   <destination>dynamicTopics/STOCKS.MSFT</destination>

     

                   <header>

                        <JMSDeliveryMode>1</JMSDeliveryMode>

                        <JMSExpiration>0</JMSExpiration>

                        <JMSPriority>4</JMSPriority>

                        <JMSMessageID>ID:localhost-1903-1340119365529-3:1:1:1:77</JMSMessageID>

                        <JMSTimestamp>1340119660654</JMSTimestamp>

                        <JMSCorrelationID />

                        <JMSType />

                        <JMSRedelivered>false</JMSRedelivered>

                        <character-set>ISO-8859-2</character-set>

                        <JMSReplyTo />

                   </header>

                   <body>

                        <text>

                             <price stock="MSFT" bid="61.93585791746035" offer="61.99779377537781" movement="down" />

                        </text>

                   </body>

            </message>

          </data>
    </adapter-event>

     

    Now that we've verified your monitor adapter is configured properly, and you're creating monitor adapter events, it's time to build some workflow.

     

    IV) Workflow - Process & Rules


    Using BAO Development Studio it's time to create our workflow module.  The workflow for our example watches for specific monitor adapter events, parses specific data (the "bid" attribute of the <price> element) and writes it a file on the server.

    The basic steps include creating a project, adding an append file process, and creating our rules.


    4.1) Create a new Project (StockQuote).  Self-Explanatory.

     

    4.2) Create a Process (call it, "WriteBid") - We start by creating our process, since the Rule must be associated with an exisiting process.

     

    The process in our example uses 3 activities: Start, Append, and Stop.  The Append activity is included in the "AutoPilot-AD-Utilities" adapter module added in the sample "Hello World" process used by BMC.  It's located:

     

    Terminal | File | Append

     

    START ACTIVITY

     

    On the Start activity you'll need to create a single input parameter called "inputevent".  The name of the parameter is important since this is what the adapter manager looks for when passing the <data> elements for all adapter events that find matching rules (below).

     

    The parameter does not have to be Global.

     

    APPEND ACTIVITY

     

    The Append activity includes 3 inputs that'll have to be configured: adapter name, file name, and line 1.  Line 1 is the actual "bid" data from our start activity and will require a little configuration. 

     

    The other two:


    Adapter Name: RO_Adapter_JMS_Localhost (The name of the file adapter configured on your grid).

    File Name: c:\stock.txt (The name of the text file on your BAO server we'll be writing to.)

     

    As mentioned, Line 1 will be the bit of data we want to write to our text file. Since it's coming in to our process as an XML attribute we'll have to convert (transform) it to text.  Using the Advanced transformation editor, select an XPath transformation and specify the following:

     

    //@bid

     

    This will extract the value of the "bid" attribute from the incoming XML.

     

    Save your changes and test the process by passing in the following XML to your Start activity:

     

    <message>

     

      <destination>dynamicTopics/STOCKS.MSFT

          </destination>

      <header>

        <JMSDeliveryMode>1</JMSDeliveryMode>

        <JMSExpiration>0</JMSExpiration>

        <JMSPriority>4</JMSPriority>

        <JMSMessageID>ID:localhost-1903-1340119365529-3:1:1:1:77</JMSMessageID>

        <JMSTimestamp>1340119660654</JMSTimestamp>

        <JMSCorrelationID />

        <JMSType />

        <JMSRedelivered>false</JMSRedelivered>

        <character-set>ISO-8859-2</character-set>

        <JMSReplyTo />

      </header>

      <body>

        <text>

          <price stock="MSFT" bid="61.93585791746035" offer="61.99779377537781" movement="down" />

        </text>

      </body>

    </message>

     

    If everything works as it should, you'll be writing the bid value of 61.93585791746035 to your c:\stock.txt file each time you run the test.

     

    4.3) Create Rules

     

    Rules are a lot like the "Run-If" qualification of a Remedy ARS Active Link or Filter.  When an action occurs (like an incoming JMS message), the adapter manger compares workflow rules to the event to see if there's a match.  If not, no further processing happens (there are no "else" rules).

     

    If there is a match, then everything within the <data> element tags of the monitor adapter event are passed to the "inputevent" parameter of the Start activity.

     

    To configure your rule you'll need to give it a name, associate it with a process (which is why we define the process first), and define the XML conditions used for the comparison.  Each rule can only be associated with a single process, but you can have multiple rules, each pointing to their own process withing the workflow.


    Our rule is associated with our process defined above:

     

    StockQuote:WriteBid

     

    The XML XPath query will be looking for the name of the adapter we configured earlier - it's handed off from the adapter manager as part of the monitor adapter event ("RO_Adapter_JMS_Localhost") and should be:


    Source: string(//source-adapter)

    Comparitor: =

    Value: "RO_Adapter_JMS_Localhost" (with quotes)

     

    Special thanks to A. Kachwala for his helpful posts on XPath, including this one:

    https://communities.bmc.com/communities/message/241318#241318

     

    Save your module and upload to the CDP repository.

     

    Congratulations, you're done!

     

    CONCLUSION


    Assuming everything is configured properly you now have full end-to-end example, including:

    • An ActiveMQ broker publishing Market Portfolio messages with a "STOCKS.MSFT" topic.
    • A BAO adapter on your grid that's subscribed to the JMS message queue.
    • A module configured with rules that match the incoming messages being processed by the BAO adapter manger.
    • A process that parses the <data> string of your incoming messages for the "bid" price of the ticker symbol, MSFT.
    • An append action that adds the bid price to end of the file.

     

    Note that if you open the file you'll be blocking the module's append action from writing to it.