Legacy JMS Input and Output Adapters

Note

This document describes an outdated and deprecated set of JMS adapters. To use StreamBase's most up-to-date and fully supported JMS connectivity solution, see Using the JMS and TIBCO EMS Operators.

Introduction

The TIBCO StreamBase® Legacy Adapter for JMS allows StreamBase to integrate with a JMS-compliant message bus. The Java Message Service (JMS) API is a Java message-oriented middleware API for sending messages between two or more clients.

Introduction to JMS

The StreamBase JMS adapters work with a JMS-compliant message bus. Java Message Service (JMS) is an API orginally defined by Sun Microsystems (now part of Oracle Corporation) for invoking operations on enterprise messaging systems. The JMS specification allows for multiple implementations called JMS providers. The StreamBase JMS adapter works with the JMS implementation of any JMS provider, but must be configured differently for each provider. This document uses configuration examples from four JMS providers:

  • TIBCO Enterprise Messaging Service™ (EMS)

  • Apache ActiveMQ

  • IBM WebSphere Application Server

  • Solace Systems

If you are connecting to a JMS server from another JMS provider, you must adapt the configuration examples and discussion on this page for the particulars of your JMS provider.

Adapter Introduction

The JMS Embedded Input Adapter is called the JMS Reader on this page. The JMS Reader is an embedded adapter that subscribes to messages from a JMS message bus.

The JMS Embedded Output Adapter is called the JMS Writer on this page. The JMS Writer is an embedded adapter that publishes messages to a JMS message bus.

An embedded adapter is an adapter that runs in the same process as StreamBase Server. The JMS Reader listens for messages from a JMS Message bus. When it receives a message, the JMS Reader creates a tuple from the message, and then sends that tuple to the operator that is downstream from it in its StreamBase application. Conversely, the JMS Writer receives tuples from StreamBase Server, creates a JMS message from it, and publishes it to the JMS Message bus.

The JMS Embedded Adapters serialize the messages they receive. That is, the StreamBase Server will process messages in the same order as they are initially received by the JMS Reader, and the JMS broker will be sent messages in the same order that the corresponding tuples are received by the JMS Writer.

The adapters have many options for configuring connections and messages, described in The JMS Embedded Adapters' Configuration File. You can edit a JMS configuration file's XML syntax directly or graphically using the JMS Configuration File Editor.

Connection To JNDI And JMS Servers

By default, the JMS adapters only try to connect to a JNDI or JMS server one time before giving up. However, you can configure the adapter to retry the connection a certain number of times at set intervals before giving up. To do this, set the server-num-retries and server-reconnect-interval attributes of the relevant <jms-server> section in the adapter's configuration file. The server-num-retries attribute controls the number of times the adapter will try to connect before giving up. The default value of this attribute is 0, which specifies no retries; the maximum value is MAX_INT. The server-reconnect-interval attribute controls the number of seconds to wait between connection attempts. The default value is 30 seconds.

Note that these values apply to both the JNDI and JMS servers configured in this <jms-server> section.

This functionality, used in conjunction with the Command Input and Status Output ports described here, can be used to implement logic to fully control the adapter's connection logic to the JMS servers it is configured to use.

Message Translation

When the JMS Reader receives a message, it translates this message into a Tuple and when the JMS Writer receives a Tuple, it translates it into a JMS message. There are five JMS message types: MapMessage, TextMessage, BytesMessage, ObjectMessage and StreamMessage. The JMS adapters include built-in support for the first three of these; this support is described in this section.

The message translation class used by the adapter for a given destination is specified using its fully-qualified Java class name in the <destination> tag's message-to-tuple-converter attribute (for JMS Readers) or tuple-to-message-converter (for JMS Writers) -- see JMS Configuration File Elements for examples.

MapMessage Converters

Converter class names:

  • com.streambase.sb.adapter.common.jms.enqueue.DefaultFromJMSMapMessageConverter (JMS Reader)

  • com.streambase.sb.adapter.common.jms.dequeue.DefaultToJMSMapMessageConverter (JMS Writer)

MapMessage is the type into which tuples translate most readily. Like a tuple, a MapMessage is a set of name-value pairs, making the translation of these two message types relatively straightforward. The JMS Reader includes a class that converts JMS MapMessages to StreamBase tuples, com.streambase.sb.adapter.common.jms.enqueue.DefaultFromJMSMapMessageConverter. Similarly the JMS Writer adapter provides com.streambase.sb.adapter.common.jms.dequeue.DefaultToJMSMapMessageConverter to translate from a Tuple to a JMS MapMessages.

StreamBase tuples and JMS MapMessages are essentially collections of name-value pairs. The JMS Reader pairs the fields held by a JMS MapMessage with fields in a StreamBase schema that have the same names and compatible types. If the name of a field in the MapMessage doesn't exist in the StreamBase schema then that field is dropped. Similarly, if the name of a field in the Schema doesn't exist in the MapMessage then there is no input value for that field and it is nulled.

In the case of the JMS Writer, all fields in the incoming Tuple are added to the MapMessage.

TextMessage Converters

Converter class names:

  • com.streambase.sb.adapter.common.jms.enqueue.DefaultFromJMSTextMessageConverter (JMS Reader)

  • com.streambase.sb.adapter.common.jms.dequeue.DefaultToJMSTextMessageConverter (JMS Writer)

TextMessages only contain one field, used to carry a text-only payload. The JMS Reader adapter will look for a suitable field (of type STRING) in its output schema to contain the payload of an incoming message using the following heuristics:

  1. If a converter-custom-settings attribute was specified for this destination, its value will be taken as the name of the StreamBase field to use.

  2. If the above search fails but a field named text, Text, payload or Payload is present, this will be used.

  3. If neither of the above searches have yielded an appropriate candidate, the first field of type STRING in the schema will be used.

The same heuristics will be employed by the JMS Writer adapter to locate the payload of incoming tuples to place in the outgoing JMS message.

Note

A common usage idiom for JMS TextMessages is to place XML data in the text payload of the message. This can easily be accommodated in a StreamBase application by combining the JMS adapters with the XML-To-Tuple and Tuple-To-XML operators to decode/encode the XML payloads.

BytesMessage Converters

Converter class names:

  • com.streambase.sb.adapter.common.jms.enqueue.DefaultFromJMSBytesMessageConverter (JMS Reader)

  • com.streambase.sb.adapter.common.jms.dequeue.DefaultToJMSBytesMessageConverter (JMS Writer)

BytesMessages only contain one field, used to carry a binary payload. The JMS Reader adapter will use the same heuristics as for the TextMessage converters to look for a suitable field (of type BLOB) in its output schema to contain the payload of an incoming message:

  1. If a converter-custom-settings attribute was specified for this destination, its value will be taken as the name of the StreamBase field to use.

  2. If the above search fails but a field named bytes, Bytes, payload or Payload is present, this will be used.

  3. If neither of the above searches have yielded an appropriate candidate, the first field of type BLOB in the schema will be used.

The same heuristics will be employed by the JMS Writer adapter to locate the BLOB payload of incoming tuples to place in the outgoing JMS message.

"Simple" Message Converters

Converter class names:

  • com.streambase.sb.adapter.common.jms.enqueue.DefaultFromJMSSimpleMessageConverter (JMS Reader)

  • com.streambase.sb.adapter.common.jms.dequeue.DefaultToJMSSimpleMessageConverter (JMS Writer)

So-called "simple" JMS messages (returned when calling javax.jms.Session.createMessage()) contain no body fields. The JMS Reader adapter will produce a tuple containing only the message's header fields (if any are configured in the schema).

Similarly, the JMS Writer adapter will send a JMS message with no body payload.

Custom Converters

Interface class names:

  • com.streambase.sb.adapter.common.jms.enqueue.FromJMSMessageConverter (JMS Reader)

  • com.streambase.sb.adapter.common.jms.dequeue.ToJMSMessageConverter (JMS Writer)

An interface is used to represent a class that can convert a JMS Message to a StreamBase tuple. This interface, com.streambase.sb.adapter.common.jms.enqueue.FromJMSMessageConverter, includes a method, Object convertFromJMSMessage(Message message) throws StreamBaseException that provides the implementation of the translation. A different translation class can be implemented, and the JMS Reader can then be configured to use this implementation. In this way, a converter to translate one of the other JMS message types can be specified, or an alternate implementation of an existing converter can be specified.

As expected, the JMS Writer also provides a similar interface, com.streambase.sb.adapter.common.jms.dequeue.ToJMSMessageConverter which includes the Message convertToJMSMessage(Object object) throws StreamBaseException method to do the opposite conversion.

Mapping Names, Headers and Properties

A JMS message consists of two primary pieces, a header and a payload (body). In addition, properties can be set on a JMS message.

By default, the JMS Embedded Adapters map the fields of a MapMessage to the fields of a StreamBase schema. The JMS Reader looks for entries in the payload of a MapMessage that have the same names as the fields of the StreamBase schema. The JMS Writer simply creates entries in the outgoing Message to match all the fields of the incoming StreamBase schema.

The JMS Embedded Adapters also provide facilities for handling other mappings, specified in the configuration file. For example, a name map can be used to map a field on a MapMessage to a field on a StreamBase schema that has a different name. Similarly, the fields in the header of a JMS message can be mapped to the fields of a StreamBase schema. In the same way, JMS properties can also be mapped to the fields of a StreamBase schema.

Note

Some JMS message headers are read-only. As such, the JMS Writer will not be able to change them even if there is an entry to that effect in the header map. When configuring header maps for use by the JMS Writer, keep in mind that only the following headers are mutable:

  • JMSCorrelationID

  • JMSReplyTo

An attempt to map any other headers for the JMS Writer results in an error.

Because the JMS Reader simply reads the JMS headers, all headers can be mapped.

The JMS Reader and Acknowledge Modes

The JMS Reader consumes messages from JMS destinations. The manner in which these messages are acknowledged is configurable within the JMS Reader. The setting for the acknowledge mode can impact the performance of the reader.

The JMS Reader fully supports acknowledge modes of AUTO_ACKNOWLEDGE and DUPS_OK_ACKNOWLEDGE. The reader also fully supports the use of TIBCO EMS' proprietary acknowledge mode, NO_ACKNOWLEDGE. Of course, use of this acknowledge mode implies that TIBCO's EMS message bus is being used with the reader. The JMS Reader only partially supports CLIENT_ACKNOWLEDGE, TIBCO EMS' EXPLICIT_CLIENT_ACKNOWLEDGE and Apache ActiveMQ's INDIVIDUAL_ACKNOWLEDGE; while there is no way for the StreamBase application to trigger an explicit acknowledgement of the message, if one of these modes is selected the adapter will wait until the tuple is fully processed by the application before acknowledging the message. This gives the application a chance to, for example, persist the message to ensure later retrieval if needed.

The acknowledge mode for a given JMS server is specified in the <jms-server> section of the configuration file, using the attribute <acknowledge-mode>.

Note also that the JMS Reader makes no effort to prevent or in any way handle the delivery of duplicate JMS messages. If a JMS server delivers the same message twice, the JMS Reader will simply consume it twice.

The JMS Writer and Delivery Modes

The JMS Writer will create JMS messages and deliver them to a JMS message bus. JMS messages can be delivered with either of two delivery modes, DeliveryMode.PERSISTENT or DeliveryMode.NON_PERSISTENT. The delivery mode for a JMS destination is specified in the destination section of the configuration file, using the delivery-mode attribute.

The semantics of JMS delivery modes is beyond the scope of this discussion. In general, a delivery mode of PERSISTENT implies a higher quality of service for the JMS destination. Some performance penalty is also implied, however. In particular, if a delivery mode of PERSISTENT is specified, and there are durable subscribers for the message, then the JMS message will need to be persisted before the JMS server can acknowledge the message producer.

Note

for TIBCO EMS users: an additional EMS-specific delivery mode is supported, RELIABLE_DELIVERY.

Destination Routing for the JMS Writer

The JMS Writer dequeues tuples from StreamBase streams, translates them into JMS messages, and routes them to JMS destinations. The adapter relies on two fields in the dequeued tuple to determine which destination on which JMS server to send the translated message. The two fields must be called __JMSServerName and __JMSDestinationName. These fields must contain the name of a configured JMS server and destination, respectively. These fields are optional if only one destination is specified in the configuration; they are required if the configuration specifies more than one destination (that is, more than one server or more than one destination in a single server).

Using a JMS Implementation

When one of the JMS Embedded Adapters executes, it needs to connect to an executing instance of a JMS message bus. Typically, this bus will be from one of the JMS providers. In order to connect to the JMS provider's JMS bus, JAR files supplied by the JMS provider must be made available to the JMS Adapters. This is true whether the adapter is executing from within StreamBase Studio or at a command-line invocation of StreamBase Server:

  • If the adapter is started from Studio, then the vendor's JMS JAR file or files must be imported into the Studio project or added to the Java Build Path of the Studio project.

  • If the adapter is executed from a command-line invocation of StreamBase Server, then the location of the vendor's JAR file or files must be specified in the <java-vm> section of the server's configuration file.

  • As an alternative, you can instead copy the JAR files to streambase-install-dir/lib/ext, which will make them available to both StreamBase Studio and StreamBase Server.

Examples for ActiveMQ users:

The following JAR files must be made available to StreamBase Studio and/or to StreamBase Server in order to successfully connect to an ActiveMQ server:

  • activemq_installdir/lib/activemq-core-5.10.0.jar (adjusting filename for your installed version of ActiveMQ)

  • activemq_installdir/lib/geronimo-j2ee-management_1.1_spec-1.0.1.jar

  • activemq_installdir/lib/hawtbuf-1.10.jar

Examples for TIBCO EMS users:

The following JAR file must be made available to StreamBase Studio and/or to StreamBase Server in order to successfully connect to a TIBCO EMS server:

  • TIBCO_EMS_installdir/lib/tibjms.jar

  • TIBCO_EMS_installdir/lib/jms-2.0.jar

Examples for Solace JMS users:

The following JAR files must be made available to StreamBase Studio and/or to StreamBase Server in order to successfully connect to a Solace JMS server:

  • STREAMBASE_installdir/lib/ext/commons-lang-2.2.jar

  • STREAMBASE_installdir/lib/ext/sol-common-5.1.1.1.jar (adjusting filename for your installed version of Solace)

  • STREAMBASE_installdir/lib/ext/sol-jcsmp-5.1.1.1.jar (adjusting filename for your installed version of Solace)

  • STREAMBASE_installdir/lib/ext/sol-jms-5.1.1.1.jar (adjusting filename for your installed version of Solace)

Important

Regardless of the JMS vendor used, you must also provide a copy of jms.jar. This file should be included in your JMS vendor's product installation alongside its other JAR files such as those mentioned above.

Adapter Properties

Settings are used to control most of the behavior of the adapter. The settings are grouped under several tabs in the Properties view in StreamBase Studio.

In the table in this section, the Property column shows each property name as found in the one or more adapter properties tabs of the Properties view for this adapter.

When using this adapter in a StreamSQL program with the APPLY JAVA statement, you may refer to property names using the StreamSQL parameter name, also included in the Property column.

General Tab

Name: Use this required field to specify or change the name of this instance of this component, which must be unique in the current EventFlow module. The name must contain only alphabetic characters, numbers, and underscores, and no hyphens or other special characters. The first character must be alphabetic or an underscore.

Adapter: A read-only field that shows the formal name of the adapter.

Class name: Shows the fully qualified class name that implements the functionality of this adapter. If you need to reference this class name elsewhere in your application, you can right-click this field and select Copy from the context menu to place the full class name in the system clipboard.

Start with application: If this field is set to Yes (default) or to a module parameter that evaluates to true, this instance of this adapter starts as part of the JVM engine that runs this EventFlow module. If this field is set to No or to a module parameter that evaluates to false, the adapter instance is loaded with the engine, but does not start until you send an sbadmin resume command, or until you start the component with StreamBase Manager.

Enable Error Output Port: Select this check box to add an Error Port to this component. In the EventFlow canvas, the Error Port shows as a red output port, always the last port for the component. See Using Error Ports to learn about Error Ports.

Description: Optionally enter text to briefly describe the component's purpose and function. In the EventFlow canvas, you can see the description by pressing Ctrl while the component's tooltip is displayed.

Adapter Properties Tab

There is only one required property for either of the JMS Embedded Adapters: its configuration file. Configuration of the adapter is fairly involved, and so is not accomplished through its properties, but rather through its configuration file. Keep in mind that just the name of the configuration file, rather than its path, should be specified in the property. The named file will be searched for using the path specified in the configuration for StreamBase itself.

There are also two optional properties to control whether the adapter should accept JMS connection/disconnection commands from the application and whether status tuples should be issued when JMS servers or destinations become available or unavailable.

The JMS Reader is similar to an input stream that gets its input from a JMS Message bus. As with an input stream, a Schema needs to be specified for the JMS Reader. The Schema used by the JMS Reader is specified in the Edit Schema tab of the Properties View in StreamBase Studio.

Property Description Default
Configuration File (required string)

StreamSQL name: ConfigFile

The name of the adapter configuration file. None
Capture Transform Strategy The strategy to use when transforming capture fields for this operator: FLATTEN or NEST. FLATTEN
Log On When Application Starts (optional)

StreamSQL name: LogonAtStartup

When set, the adapter will attempt to connect to the configured server(s) when the applications is started. Otherwise the adapter will wait for an explicit "Connect" command (see Command Input Port Schema) before attempting connection. True
Add Command Input Port (optional)

StreamSQL name: UseCommandInputPort

If checked, this option will cause the adapter to expose a new input port that will be used to receive commands from the application.

The schema and semantics of this port are described below.

None
Add JMS Status OutputPort (optional)

StreamSQL name: UseStatusOutputPort

If checked, this option causes the adapter to expose a new output port used to send status tuples when interesting events occur on the configured JMS server(s).

The schema and semantics of this port are described below.

None
Log Level Controls the level of verbosity the adapter uses to send notifications to the console. This setting can be higher than the containing application's log level. If set lower, the system log level will be used. Available values, in increasing order of verbosity, are: OFF, ERROR, WARN, INFO, DEBUG, TRACE. INFO
Log Level (optional)

StreamSQL name: logLevel

Controls the level of verbosity the adapter uses to issue informational traces to the console. This setting is independent of the containing application's overall log level. Available values, in increasing order of verbosity, are: OFF, ERROR, WARN, INFO, DEBUG, TRACE, and ALL. INFO
Log Full Callstacks (optional)

StreamSQL name: LogFullCallstacks

When set, the adapter will print full call stacks when an exception happens, regardless of the Log Level set above. Otherwise only an exception's message will be printed unless the Log Level is DEBUG. False

The JMS Embedded Adapters' Configuration File

The JMS Embedded Adapters are configured using an XML configuration file having a .jmsconf file extension. This configuration file consists of two types of information, JMS configuration and configuration concerning the translation of JMS messages to tuples and back.

You can edit a JMS configuration file's XML syntax directly or graphically using the JMS Configuration File Editor.

It may be that many JMS destinations need to be specified in the configuration file for the JMS Embedded Adapters. Where applicable, it is possible to specify a default value for a configuration attribute of a destination. The default can then be overridden by specifying a value for a particular destination.

A sample configuration file for both the JMS Reader and JMS Writer are included with the JMS sample that is included in the StreamBase distribution, under the configurationFileReference subdirectory of the sample. These files include comments describing the various XML elements and attributes that make up the configuration. These sample configuration files can be used as a template for configuration files. These files can also be obtained by executing the jmsadapter.jar JAR file. For Linux:

java -jar streambase-install-dir/lib/adapter/jmsadapter.jar reader

For Windows:

java -jar "streambase-install-dir\lib\adapter\jmsadapter.jar reader"

Similarly, the JMS Writer has a sample configuration file which can be displayed by executing the jmsadapter.jar JAR file with a different parameter. For Linux:

java -jar streambase-install-dir/lib/adapter/jmsadapter.jar writer

For Windows:

java -jar "streambase-install-dir\lib\adapter\jmsadapter.jar writer"

Configuration Examples

Here are some typical settings for connecting to JMS servers from TIBCO EMS, ActiveMQ, IBM WebSphere, and Solace Systems:

TIBCO EMS (using JNDI)

<jms-servers>
  <jms-server name="EMSServer" 
    provider-context-factory="com.tibco.tibjms.naming.TibjmsInitialContextFactory" 
    provider-url="tibjmsnaming://localhost:7222" 
    connection-factory-name="ConnectionFactory" 
    acknowledge-mode="NO_ACKNOWLEDGE"/>
</jms-servers>

ActiveMQ version 5.x (using JNDI)

<jms-servers>
  <jms-server name="ActiveMQServer" 
    provider-context-factory="org.apache.activemq.jndi.ActiveMQInitialContextFactory"
    provider-url="tcp://localhost:61616"
    connection-factory-name="ConnectionFactory"
    acknowledge-mode="AUTO_ACKNOWLEDGE"/>
</jms-servers>

IBM WebSphere Application Server version 6.1's Default JMS Implementation (using JNDI)

<jms-servers>
  <jms-server name="server1" 
    provider-context-factory="com.ibm.websphere.naming.WsnInitialContextFactory"
    provider-url="iiop://localhost:2809"
    connection-factory-name="jms/MyConnFactory"
    jndi-initial-context-builder="com.streambase.sb.adapter.common.jms.common.WASJNDIInitialContextBuilder"
    create-destinations="false"
    acknowledge-mode="AUTO_ACKNOWLEDGE"/>
</jms-servers>

Solace default JMS Implementation (using JNDI)

<jms-servers>
  <jms-server name="solaceJms" 
    provider-context-factory="com.solacesystems.jndi.SolJNDIInitialContextFactory"
    provider-url="smf://MyProviderHost:MyProviderPort"
    connection-factory-name="MyConnFactory"
    acknowledge-mode="AUTO_ACKNOWLEDGE"
    jndi-security-principal="MySecurityPrincipal"
    jndi-security-credentials="MySecurityCredentials"
    jndi-initial-context-builder="com.streambase.sb.adapter.common.jms.common.SolaceJNDIInitialContextBuilder"
    username="MyUsername"
    create-destinations="true"
    password="MyPassword" >
    <jndi-extra-properties>
      <extra-property name='Solace_JMS_OptimizeDirect' value='false'/>
      <extra-property name='Solace_JMS_VPN' value='MyJmsVpn'/>
    </jndi-extra-properties>
  </jms-server>
</jms-servers>

JMS Configuration File Elements

The JMS configuration file is in XML format. For reference, the following listing shows the complete set of valid elements for the JMS input configuration file.

<?xml version="1.0" encoding="UTF-8"?>
<sb-jms-adapter-config
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="http://www.streambase.com/schemas/sbjmsreader/"
	adapter-class="com.streambase.sb.adapter.jms.enqueue.JMSReader"
	>
                                                                               
  <!--
  
  	NAME MAPS

    By default, this adapter will match JMS fields with StreamBase fields 
    when they share the same name.
    This behavior can be overridden with a 'name map'.  A name map is used 
    to associate a JMS field and a StreamBase field when they do not share 
    the same name.
    
    A set of name maps can be specified.  Each configured destination can 
    use a different name map.  Name maps are themselves named and are 
    referred to by name.
    
  -->
  <name-maps>

    <name-map name="MyNameMap">

      <!--
      	A name map consists of a set of mappings, each associates a JMS 
        field with a StreamBase field that has a different name.
      -->
      <mapping jms-name="symbol" sb-name="ticker_symbol"/>
      <mapping jms-name="bid" sb-name="value"/>
      
    </name-map>

    <!--
      A second name map.
    -->
    <name-map name="MSFTConversion">
    
      <mapping jms-name="MSFTsymbol" sb-name="ticker_symbol"/>
      
    </name-map>
  </name-maps>

  
  <!--
    If many destinations use the same name map, it may be convenient to 
    specify a default.
  -->
  <default-name-map>MyNameMap</default-name-map>



  <!--
  
  	JMS HEADER MAPS

    A JMS message is delivered with a set of standard JMS header fields.  
    Header fields can be mapped to StreamBase fields using a 
    jms-header-map.

    A set of header maps can be specified.  Each configured destination
    can use a different header map.  Header maps are named and are 
    referred to by name.
    
  -->
  <jms-header-maps>

    <jms-header-map name="MyHeaderMap">

      <!--
      	A JMS header map consists of a set of mappings.  Each mapping 
      	associates a JMS header with a StreamBase field.  The value of the 
      	JMS header field will be written to the StreamBase field.
      -->
      <mapping jms-name="JMSTimestamp" sb-name="jms_timestamp"/>
    </jms-header-map>
  </jms-header-maps>

  <!--
  	If many destinations use the same header map, it may be convenient to 
  	specify a default.
  -->
  <default-jms-header-map>MyHeaderMap</default-jms-header-map>


  <!--
  
  	JMS PROPERTY MAPS

  	Either a JMS provider or a message creator can add properties to a JMS 
    message.  Properties can be thought of as provider or user defined 
    headers.

  	As with headers, a map is used to associate a property with a 
    StreamBase field.  A mapping associates a JMS property with a 
    StreamBase field, causing the value of the property to be written to 
    the StreamBase field.

  	A set of property maps can be specified.  Each configured destination 
    can use a different property map.  Property maps are named and are 
    referred to by name.
    
  -->
  <jms-property-maps>

    <jms-property-map name="MyJMSPropertyMap">

      <!--
        A JMS property map consists of a set of mappings.  Each mapping 
        associates a JMS property with a StreamBase field.  The value of 
        the JMS property will be written to the StreamBase field.
      -->
      <mapping jms-name="StartTime" sb-name="start_time"/>
      <mapping jms-name="EndTime" sb-name="end_time"/>
    </jms-property-map>
  </jms-property-maps>

  <!--
    If many destinations use the same property map, it may be convenient to 
    specify a default.
  -->
  <default-jms-property-map>MyJMSPropertyMap</default-jms-property-map>



  <!--
  
  	TIMESTAMP FORMATS

  	StreamBase represents a timestamp as a type 
       com.streambase.sb.Timestamp.

  	Fields, properties or headers delivered in a JMS message may represent 
    timestamps, but they will not be of this type.

  	A timestamp format can be used when a JMS field, header, or property 
    delivers a timestamp that is represented as a string.  The timestamp 
    format is used to specify the format of the string so that it can be 
    translated to a com.streambase.sb.Timestamp.

  	A set of timestamp formats can be specified.  Each configured 
    destination can use a different timestamp format.  Timestamp formats 
    are named and are referred to by name.
    
  -->
  <timestamp-formats>    
    <timestamp-format name="MyTimestampFormat" 
                      format="MM/dd/yyyy hh:mm:ss aa"/>
  </timestamp-formats>

  <!--
  	If many destinations use the same timestamp format, it may be 
    convenient to specify a default.
  -->
  <default-timestamp-format>MyTimestampFormat</default-timestamp-format>



  <!--
  
  	DEFAULT DELIVERY TIME FIELD

  	It may be useful to mark a StreamBase tuple with a timestamp indicating 
    when the tuple was delivered to the StreamBase application.

  	The delivery time attribute is used to specify a field on the 
    StreamBase tuple to mark with the delivery time.

  	If many destinations set the same delivery time field, it may be 
    convenient to set a default.
    
  -->
  <default-delivery-time-field>arrival_time</default-delivery-time-field>



  <!--
  
  	DEFAULT MESSAGE TO TUPLE CONVERTER

  	This adapter converts JMS messages to StreamBase tuples.  
    The software responsible for this functionality is represented by an 
    interface, 
    com.streambase.sb.adapter.common.jms.enqueue.FromJMSMessageConverter.
    A default implementation of FromJMSMessageConverter is supplied.

  	It may be that a custom implementation of FromJMSMessageConverter is 
    needed however.  For each configured destination, it is possible to 
    specify a custom implementation of FromJMSMessageConverter.

  	If many destinations set the same FromJMSMessageConverter, it may be 
    convenient to set a default value.
  -->
  <default-message-to-tuple-converter>com.streambase.sb.adapter.common.jms.enqueue.DefaultFromJMSMapMessageConverter</default-message-to-tuple-converter>


  <!--
  
    DEFAULT CONVERTER CUSTOM SETTINGS

  	If many destinations set the same converter custom settings, it may be 
    convenient to set a default.
    
    Because the format of this string is arbitrary, some care should be taken to keep it
    valid within this XML file. For example, embedding a "greater than" sign may require
    the use of "&gt;"
    
  -->
  <default-converter-custom-settings>Insert your default custom settings here</default-converter-custom-settings>


  <!--
  
  	JMS SERVERS

  	This adapter subscribes to messages from one or more JMS message buses.
    Each JMS message bus is configured using a jms-server element in this 
    config file.
    
  -->
  <jms-servers>

    <!--
    
      JMS SERVER
      
      A JMS server is configured using the attributes of the jms-server 
      element.
      
      Two different sets of attributes are supported, one for connecting to a
      JMS server using JNDI, and one for connecting to a JMS server without using JNDI.

      Name is used in either case.
      	- name:  Each JMS server is named and can be referred to by name.
      	  This parameter is required.
      	
      To connect to a JMS server using JNDI (LDAP, etc.) an initial JNDI Context is instantiated
      using values for Context.INITIAL_CONTEXT_FACTORY and Context.PROVIDER_URL (among others; see below.)
      Values for these are specified as attributes on the JMS server element:

      	- provider-context-factory:  This attribute is used to specify a 
          value for Context.INITIAL_CONTEXT_FACTORY.
      	  This parameter is required.
          
      	- provider-url:  This attribute is used to specify a value for 
          Context.PROVIDER_URL.
      	  This parameter is required.
          
      	- connection-factory-name:  A connection factory to be looked up
      	  by name via a JNDI lookup. This will then be used to construct
      	  the connection object.
      	  This parameter is required.
          
      In addition, a host of optional settings are available to help set up the proper
      InitialContext for JNDI lookups:
    
        - jndi-security-principal:      Corresponds to javax.naming.Context.SECURITY_PRINCIPAL
        - jndi-security-credentials:    Corresponds to javax.naming.Context.SECURITY_CREDENTIALS
        - jndi-security-authentication: Corresponds to javax.naming.Context.SECURITY_AUTHENTICATION
        - jndi-security-protocol:       Corresponds to javax.naming.Context.SECURITY_PROTOCOL
        - jndi-authoritative:           Corresponds to javax.naming.Context.AUTHORITATIVE
        - jndi-dns-url:                 Corresponds to javax.naming.Context.DNS_URL
        - jndi-referral:                Corresponds to javax.naming.Context.REFERRAL
        - jndi-initial-context-builder: Full-qualified name of the Java class implementing
                                        com.streambase.sb.adapter.common.jms.common.JNDIInitialContextBuilder,
                                        which is responsible for creating the JNDI InitialContext object
                                        based on the settings described here.
        - jndi-extra-properties:        Defines additional properties that may be required
                                        beyond those defined in javax.naming.Context.
          
        This latter node is expected to contain an arbitrary number of sub-nodes
        named 'extra-property' with attributes named 'name' and 'value'.

      To connect to JMS WITHOUT using JNDI, you must specify the name of a class implementing
      javax.jms.ConnectionFactory, as well as the URL to use:

      - connection-factory-class:  The name of the connection factory class to instantiate.
        It is assumed that this class implements a constructor taking one String parameter
        that represents the URL of the JMS broker.
      - connection-factory-url:  The broker URL to pass to the connection factory at construction time.

      The following optional settings are available to help create and manage a connection to JMS:
              
        - client-id:  If desired, a specific ClientID value may be set
          on the connection. This will result in the adapter
          calling javax.jms.Connection.setClientID() with the supplied
          value.
          
        - subscriber-name: If specified, causes a durable subscription
          to be made/used with the specified subscriber name.  Valid
          only when used in conjunction with destinations that are
          Topics.
          
        - username:  The username to use when connecting to JMS.
        
        - password:  The password to use when connecting to JMS.
          
      	- acknowledge-mode:  The mode that is used to acknowledge JMS 
          messages.  Defaults to AUTO_ACKNOWLEDGE.  Other values include:
              - DUPS_OK_ACKNOWLEDGE
              - CLIENT_ACKNOWLEDGE
              - NO_ACKNOWLEDGE (TIBCO EMS-specific)
              - EXPLICIT_CLIENT_ACKNOWLEDGE (TIBCO EMS-specific)
              - EXPLICIT_CLIENT_DUPS_OK_ACKNOWLEDGE (TIBCO EMS-specific)
              - INDIVIDUAL_ACKNOWLEDGE (Apache ActiveMQ-specific)
          
      	- create-destinations:  Whether destinations should be created or 
          looked up in JNDI.  If supported by the JMS provider, destinations 
          can be created even if they exist.  Creating destinations is faster 
          than looking them up in JNDI.  By default destinations are 
          created.
          
      	- cache-destinations:  Whether destinations should be cached once 
          created. The default value of "true" offers better performance,
          however if you are creating thousands of destinations caching them
          may adversely affect your memory footprint. 
          
      	- use-topics:  If this attribute is true, then destinations will be treated as 
          Topics, otherwise they will be treated as Queues.  The default is 
          to treat destinations as Topics (i.e. "true").
          
        - server-num-retries:  The number of times the adapter should retry
          to connect to the JMS server (and/or the JNDI server) before giving up.
          Negative values are not allowed, and the highest allowed value
          is 2147483647 (Java's Integer.MAX_VALUE).

        - server-reconnect-interval:  The number of seconds to wait between each
          connection retry.

        - destination-monitor-interval:  The number of milliseconds to wait between
          attempts to monitor the health of subscribed destinations on this server.
          A value of 0 (which is the default) indicates no monitoring should be attempted,
          and so the StreamBase application will never be notified of
          availability/unavailability of destinations on this server.

        - connection-builder:  The fully-qualified name of a class that implements
          com.streambase.sb.adapter.common.jms.common.ConnectionBuilderInterface, which
          will be responsible for creating and initializing JMS Connection objects.
          If this parameter is not specified, the adapter's default implementation
          will be used. You may use the "custom-settings" attribute (see below) to
          pass along arbitrary strings to this class.

        - custom-settings:  An arbitrary string passed verbatim to the implementer
          of the CustomConnectionBuilder interface (see the connection-builder
          attribute above.)

      DEFAULT VALUES FOR JMS-SERVERS SECTION
    
      It may be convenient to set default values for some of the settings above. These will be
      used for every jms-server entry below unless noted otherwise.
    
      Available default settings are:
    
        - default-server-num-retries
        - default-server-reconnect-interval
        - default-client-id
        - default-subscriber-name
        - default-jndi-security-principal
        - default-jndi-security-credentials
        - default-jndi-security-authentication
        - default-jndi-security-protocol
        - default-jndi-authoritative
        - default-jndi-dns-url
        - default-jndi-referral
        - default-connection-builder
        - default-jms-server-custom-settings
        - default-destination-monitor-interval
        - default-jndi-initial-context-builder
        - default-jndi-extra-properties

        This latter contains sub-nodes called 'extra-property', whose 'name' and 'value'
        attributes are passed to the JNDI InitialContext as additional environment properties.
        This can be useful when dealing with JNDI providers that require custom environment
        properties beyond those defined in the javax.naming.Context interface.
    -->
    
    <default-jndi-security-principal>MySecurityPrincipal</default-jndi-security-principal>

    <default-jndi-extra-properties>
        <extra-property name="DefaultSetting1" value="Value1" />
        <extra-property name="DefaultSetting2" value="Value2" />
    </default-jndi-extra-properties>
    
    <jms-server 
      name="EMS-SERVER" 
      
      description="This describes the JMS server"
      
      provider-name="TIBCO EMS"

      provider-context-factory="com.tibco.tibjms.naming.TibjmsInitialContextFactory" 

      provider-url="tibjmsnaming://localhost:7222" 

      connection-factory-name="GenericConnectionFactory" 

      acknowledge-mode="NO_ACKNOWLEDGE"

      create-destinations="true"

      server-num-retries="3"

      server-reconnect-interval="5"

      use-topics="true">

        <!--
        To connect to the server without using JNDI, specify connection-factory-class
        and connection-factory-url.
        -->
        <!--
        <jms-server name="tibcoServer2" 
            
                   create-destinations="true"
                   use-topics="true"

                   connection-factory-class="com.tibco.tibjms.TibjmsTopicConnectionFactory"
                   connection-factory-url="localhost"/>
        -->


      <!--
      These (optional) settings will be passed to the JNDI InitialContext as additional
      Context environment properties.
      This can be useful when the JNDI service provider requires custom properties in addition
      to the standard properties defined in the javax.naming.Context interface.
      -->
      <jndi-extra-properties>
          <extra-property name="Setting1" value="Value1" />
          <extra-property name="Setting2" value="Value2" />
      </jndi-extra-properties>

      <!--
      	The set of destinations on this JMS server that the adapter 
        subscribes to is listed here.
      -->
      <destinations>
      
        <!--
          Each destination is configured with a set of attributes.  A 
          default is provided where possible as there may be many 
          destinations.
          
          If an attribute is left unspecified for a destination, then the 
          default value of that attribute is used.  For example, if the 
          name map is left unspecified then the default name map is used.  
          If the attribute is left unspecified and no default is specified, 
          then the associated operation is not done.  For example, if no 
          name map is specified and there is no default name map, then no 
          name mapping is done.
          
            - name:  A destination is created or looked by name.

            - is-topic:  'true' if this destination is a topic, 'false' if
              it's a queue.

            - message-selector:  The message selector expression (if any) to
              use for this destination.
          	
            - name-map:  The name map used for this destination.  If 
              specified, the name map must be included in 'name-maps'.
              
            - jms-header-map:  The header map used for this destination.  If 
              specified, the header map must be included in 
              'jms-header-maps'.
              
            - jms-property-map:  The property map used for this destination.  
              If specified, the property map must be included in 
              'jms-property-maps'.
              
            - timestamp-format:  The string format used by timestamp fields 
              delivered by this destination.  The timestamp format must be 
              specified in the timestamp-formats section.
              
            - delivery-time-field:  The field on the StreamBase tuple that 
              will be marked with the delivery time.
              
            - message-to-tuple-converter:  The class used to translate JMS 
              messages to StreamBase tuples.  If message-to-tuple-converter 
              is not specified, then default-message-to-tuple-converter is 
              used.

            - converter-custom-settings:  This is a string that is passed verbatim to
              the specified message-to-tuple-converter. It allows implementers to pass
              arbitrary values to their converter. The implementing converter code is
              the sole responsible for parsing and interpreting this string. 
        -->
        <destination 
          name="topics.IN.MSFT"

          name-map="MSFTConversion"

          jms-header-map="MyHeaderMap"

          jms-property-map="MyJMSPropertyMap"

          timestamp-format="MyTimestampFormat"

          delivery-time-field="arrival_time"

          converter-custom-settings="ArbitraryKey=ArbitraryValue,AnotherKey=AnotherValue"

          message-to-tuple-converter="com.streambase.sb.adapter.common.jms.enqueue.DefaultFromJMSMapMessageConverter"

          is-topic="true"
        />

        <!--
          In addition to explicit destination definitions handled by the <destination> tags,
          a <default-destination> may be specified which will be used when creating new
          destinations (i.e. when the <jms-server create-destinations=true />).

          The syntax is the same as for the <destination> tag above except the 'name' attribute is ignored.

          At most ONE <default-destination> tag may be specified for each <jms-server>.
        -->
        <default-destination
          name-map="MyNameMap"

          jms-header-map="MyHeaderMap"

          jms-property-map="MyJMSPropertyMap"

          timestamp-format="MyTimestampFormat"

          delivery-time-field="arrival_time"

          converter-custom-settings=""

          message-to-tuple-converter="com.streambase.sb.adapter.common.jms.enqueue.DefaultFromJMSMapMessageConverter"
        />

      </destinations>
    </jms-server>
  </jms-servers>

</sb-jms-adapter-config>

Adapter Port Schemas

Command Input Port Schema

The command input port may be used by the application to request connections or disconnections to a configured JMS server, or to pause or resume processing for a JMS destination.

If the adapter is configured to expose a command input port, its schema is expected to have the following fields:

Field Name Type Description Required
server string The name of the JMS server to which this command applies. Yes
destination string The name of the JMS destination to which this command applies. This field may be left null if the command applies to the entire server instead of a single destination. Yes
command string The actual command to execute. Accepted values are described below. Note that case is unimportant. Yes

Permitted values for the command field are the following (case is unimportant):

  • Connect: Establish a connection to the specified JMS server. Attempting to connect to an already-connected JMS server has no effect. When using Connect, the destination field is ignored and can be left null.

  • Disconnect: Sever the connection to the specified JMS server. Disconnecting from an already-disconnected JMS server has no effect. When using Disconnect, the destination field is ignored and can be left null.

  • Pause: For an enqueuing adapter, JMS messages are still read from the specified destination on the specified server but are longer converted to tuples and sent to the application. For a dequeuing adapter, tuples are still dequeued from the application's stream, but are no longer converted to JMS messages and sent to the specified destination on the specified server. Pausing an already-paused destination has no effect.

  • Resume: For an enqueuing adapter, JMS messages are read from the specified destination on the specified server, and will now be converted to tuples and sent to the application. For an dequeuing adapter, tuples dequeued from the application's stream are now converted to JMS messages and sent to the specified destination on the specified server. Resuming an already-resumed destination has no effect.

  • CreateDestination: This command is only recognized by enqueuing adapters. It will cause the adapter to attempt to create the specified destination on the specified JMS server (or on all configured JMS Servers if the server field is left null). This command will only be successful if the create-destinations="true" attribute was specified in the configuration file's JMS server definition, and a default-destination section was also specified for that server (see Dynamic Endpoints).

Status Output Port Schema

The status output port can be used by the application to receive tuples describing status events for configured JMS servers (connection and disconnection) and optionally for destinations (available or unavailable.)

If the adapter is configured to expose a status output port, its schema has the following fields:

Field Name Type Description Required
server string The name of the JMS server on which this event occurred. Yes
destination string The name of the JMS destination for which this event is generated. This field may be left null if the event applies to the entire server instead of a single destination. Yes
status string The actual event that occurred. Possible values are described below. Yes
time timestamp The time at which this event was detected. Yes

Possible values for the status field are:

  • Connecting: The adapter is attempting to connect to the named JMS server. Note that the destination field is left null.

  • Connected: The named JMS server is now connected. Note that the destination field is left null.

  • Disconnected: The named JMS server has disconnected. Note that the destination field is left null.

  • Available: The named destination on the named JMS server is now available.

  • Unavailable: The named destination on the named JMS server is now unavailable.

  • Connection Failed: The connection attempt to the named JMS server failed. Note that the destination field is left null.

  • Connection Retries Exceeded: The number of connection attempts specified in the adapter's cofiguration file for the named JMS server have been exhausted. No more attempts will be made unless a new Connect command is issued (see Command Input Port Schema). Note that the destination field is left null.

Destination Monitoring

Monitoring of JMS server connections is always enabled. However, in order to receive status tuples relating to destinations becoming available or unavailable, the adapter must periodically check whether a destination is active. Because this is an intrusive process (at least minimally), this functionality is disabled by default. To enable monitoring of JMS destinations on a given JMS server, add a destination-monitor-interval attribute to this JMS server's <jms-server> section in the adapter's configuration file. The value for this attribute is the number of milliseconds the adapter should wait between destination health checks. A value of 0 disables the functionality, as does removing the attribute.

Dynamic Endpoints

By default the JMS adapters expect the endpoints (topics or queues) it will use to have been defined in the destinations section of their respective JMS server definitions in the configuration file. However, in some cases it may be desirable to have endpoints created on the fly instead (assuming the JMS server allows it). This section describes how to configure and use the JMS adapters to accomplish this.

Configuring the Adapter to Create Endpoints

First, you must tell the JMS adapter what kind of destination you wish to create by adding a default-destination entry to your JMS server's destinations section in the adapter's configuration file. The syntax to this section is identical to that of regular destination entries, except that the name attribute is ignored. You must also make sure that the JMS server's definition includes a create-destinations="true" attribute:

<jms-servers>
  <jms-server name="myJMSServer" 
    provider-context-factory="..."
    provider-url="..."
    connection-factory-name="MyConnFactory"
    acknowledge-mode="AUTO_ACKNOWLEDGE"
    jndi-security-principal="MySecurityPrincipal"
    jndi-security-credentials="MySecurityCredentials"
    jndi-initial-context-builder="..."
    create-destinations="true"
    username="MyUsername"
    password="MyPassword" >
    <destinations>
      <default-destination name-map="MyNameMap" use-topics="true"/>
      <destination name="topics.test1" name-map="MyNameMap"/>
    </destinations>
  </jms-server>
</jms-servers>

Creating Endpoints Using the Adapter

The way endpoints are created dynamically at runtime depends on whether you wish to publish or subscribe to the new endpoint — in other words, it depends on whether you are using the JMS Reader or JMS Writer adapter.

JMS Reader

To create, subscribe to, and receive JMS messages from a dynamic endpoint, you must send a CreateDestination command to the adapter's Command port (see Command Input Port Schema).

JMS Writer

To create and send JMS messages to a dynamic endpoint, send a tuple to the adapter's message port as you would normally, setting the __JMSServerName appropriately and the __JMSDestinationName to the name of the endpoint you wish to create. If the name of the destination is not found among the list of pre-configured destinations, it will create it before sending the message.

Typechecking and Error Handling

The JMS Reader performs two checks during typechecking. The JMS Reader ensures that a Schema has been defined and that a value for its configuration file has been specified.

The JMS Writer performs two checks during typechecking. It ensures that a value for its configuration file has been specified and that the input schema contains the fields __JMSServerName and __JMSDestinationName, if they are required.

If the Add Command Input Port or Add JMS Output Port options are selected, the adapters ensure that the corresponding schemas contain the expected fields. See here for a description of the expected schemas for these ports.

Suspend and Resume Behavior

On suspend, if either of the JMS Embedded Adapters is currently processing a message, it finishes processing that message or tuple to completion before suspending. That is, the StreamBase application itself finishes processing the message or tuple before the JMS adapter returns from a suspend command. Once this has occurred, the JMS Reader unsubscribes for messages. If any messages (or tuples for the JMS Writer) are delivered while the JMS adapter is suspended, it drops the messages or tuples and fails to acknowledge them.

On resume, the JMS Reader resubscribes for messages. The JMS adapters begin processing newly delivered messages/tuples once it has returned from the resume command.