~~ Licensed to the Apache Software Foundation (ASF) under one
~~ or more contributor license agreements. See the NOTICE file
~~ distributed with this work for additional information
~~ regarding copyright ownership. The ASF licenses this file
~~ to you under the Apache License, Version 2.0 (the
~~ "License"); you may not use this file except in compliance
~~ with the License. You may obtain a copy of the License at
~~
~~ http://www.apache.org/licenses/LICENSE-2.0
~~
~~ Unless required by applicable law or agreed to in writing,
~~ software distributed under the License is distributed on an
~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~~ KIND, either express or implied. See the License for the
~~ specific language governing permissions and limitations
~~ under the License.

JMS Transport

* {Content}

%{toc|section=1|fromDepth=1}

* {Transport configuration}

  Connection factories are configured using parameters in the transport description in
  <<<axis2.xml>>>. The syntax is the same for the transport listener and sender. For example,
  the following configuration sets up the JMS listener with three connection factories:

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

  If a connection factory named <<<default>>> (as shown above) is defined, this would be used for services which does
  not explicitly specify the connection factory that should be used. The <<<services.xml>>> of a service should indicate
  the connection factory and the destination name to be associated with. If a destination is not specified, the
  implementation would create a JMS Queue with the service name. The JMS destination should ideally be created
  and administered through the JMS provider utilities.
  
  For the JMS sender, only the outer element is different:
  
+----------------------------+  
<transportSender name="jms" class="org.apache.axis2.transport.jms.JMSSender">
    ...
</transportSender>
+----------------------------+  

  As explained below, for the JMS sender configuration it is not mandatory (but recommended) to specify
  connection factories.
  
  The parameters that may appear in a connection factory configuration are defined as follows:
  
    [<<<java.naming.factory.initial>>>]
    REQUIRED - JNDI initial context factory class. The class must implement the java.naming.spi.InitialContextFactory interface. 
    
    [<<<java.naming.provider.url>>>]
    REQUIRED - URL of the JNDI provider
    
    [<<<transport.jms.ConnectionFactoryJNDIName>>>]
    REQUIRED - The JNDI name of the connection factory

    [<<<java.naming.security.principal>>>]
    JNDI Username

    [<<<java.naming.security.credentials>>>]
    JNDI password

    [<<<transport.Transactionality>>>]
    Desired mode of transactionality. possible values are 'none', 'local' or 'jta', while it defaults to 'none'

    [<<<transport.UserTxnJNDIName>>>]
    JNDI name to be used to require user transaction

    [<<<transport.CacheUserTxn>>>]
    Whether caching for user transactions should be enabled or not. Possible values are 'true' or 'false', while the value defaults to 'true'

    [<<<transport.jms.SessionTransacted>>>]
    Whether the JMS session be transacted or not. Possible values are 'true' or 'false', while the value defaults to 'true' if the transactionality is 'local'

    [<<<transport.jms.SessionAcknowledgement>>>]
    JMS session acknowledgement mode. Possible values are AUTO_ACKNOWLEDGE, CLIENT_ACKNOWLEDGE, DUPS_OK_ACKNOWLEDGE, SESSION_TRANSACTED. Default value is AUTO_ACKNOWLEDGE

    [<<<transport.jms.ConnectionFactoryType>>>]
    Type of the connection factory. Possible values are 'queue' or 'topic' while the default value of 'queue'
    
    [<<<transport.jms.JMSSpecVersion>>>]
    JMS API version. Possible values are 1.1 or 1.0.2b, and the default API version is 1.1

    [<<<transport.jms.UserName>>>]
    The JMS connection username

    [<<<transport.jms.Password>>>]
    The JMS connection password

    [<<<transport.jms.DefaultReplyDestination>>>]
    JNDI name of the default reply destination
    
    [<<<transport.jms.DefaultReplyDestinationType>>>]
    Default type of the reply destination, if not provided the destination type will be taken as the reply destination type as well

    [<<<transport.jms.MessageSelector>>>]
    Message selector implementation

    [<<<transport.jms.SubscriptionDurable>>>]
    Whether the connection factory is subscription durable or not. Possible values are 'true' or 'false', while the value defaults to 'false'

    [<<<transport.jms.DurableSubscriberName>>>]
    Name of the durable subscriber. This is required if the above parameter is set to 'true'

    [<<<transport.jms.PubSubNoLocal>>>]
    Whether the messages should be published by the same connection they were received. Possible values are 'true' or 'false', while the value defaults to 'false'

    [<<<transport.jms.CacheLevel>>>]
    JMS resource cache level. Possible values are 'none', 'connection', 'session', 'consumer', 'producer', 'auto' and defaults to 'auto'
    
    [<<<transport.jms.ReceiveTimeout>>>]
    Time to wait for a JMS message during polling. Set this parameter value to a negative integer to wait indefinitely. Set to zero to prevent waiting and the default value is 1000ms

    [<<<transport.jms.ConcurrentConsumers>>>]
    Number of concurrent threads to be started to consume messages when polling. Defaults to 1, and the value should be a positive integer. For topics it has to be always 1

    [<<<transport.jms.MaxConcurrentConsumers>>>]
    Maximum number of concurrent threads to use during polling. Defaults to 1, and the value should be a positive integer. For topics it has to be always 1

    [<<<transport.jms.IdleTaskLimit>>>]
    The number of idle runs per thread before it dies out, which defaults to 10

    [<<<transport.jms.MaxMessagesPerTask>>>]
    The maximum number of successful message receipts per thread. Defaults to -1 meaning the infinity

    [<<<transport.jms.InitialReconnectDuration>>>]
    Initial reconnection attempts duration in milliseconds, which defaults to 1000ms

    [<<<transport.jms.ReconnectProgressFactor>>>]
    Factor by which the reconnection duration will be increased, which defaults to 2.

    [<<<transport.jms.MaxReconnectDuration>>>]
    Maximum reconnection duration in milliseconds, which defaults to 3600000ms (1 hr)

* {Transport listener}

** {JMS connections and message dispatching}

  Every deployed service for which the JMS transport is enabled will be associated with a
  destination (queue or topic) according to the following rules:

    * If the service has a <<<transport.jms.Destination>>> parameter, its value is interpreted
      as the JNDI name of the destination.
    
    * Otherwise the service name is used as the JNDI name of the destination.
  
  At the same time, the connection factory is determined by looking at the service parameter
  <<<transport.jms.ConnectionFactory>>>. If this parameter is not set, the default value
  <<<default>>> is assumed. The value of this parameter is interpreted as a logical identifier
  for the connection factory configuration defined in the transport configuration (see above).

  It follows that JMS destinations are statically bound to services. Therefore the transport
  always predispatches incoming messages to the service the destination is bound to.

  The message is dispatched to an operation according to the following rules:

    * The transport looks for a service parameter <<<Operation>>>. If this parameter is not present,
      the default value <<<urn:mediate>>> is assumed.
    
    * If the service has an operation with the corresponding name, the transport predispatches
      the message to that operation.
    
    * If no such operation exists, the message will be dispatched by the Axis2 engine using the
      configured dispatchers.
  
  In addition, if the JMS message has a property named <<<SOAPAction>>>, the value of this property
  is interpreted as the SOAP action.

** {Service configuration}

  Apart from the following list most of the parameters defined in the global connection factory can be overriden at the service level as well

  [<<<transport.jms.ConnectionFactory>>> (Optional)]
  The JMS connection factory definition (from <<<axis2.xml>>>) to be used to
  listen for messages for this service.
  
  [<<<transport.jms.Destination>>> (Optional)]
  The JMS destination name (Defaults to a Queue with the service name).

  [<<<transport.jms.DestinationType>>> (Optional)]
  The JMS destination type. Accept values 'queue' or 'topic' (default: queue).
  
  [<<<transport.jms.ReplyDestination>>> (Optional)]
  The destination where a reply will be posted.
  
  [<<<transport.jms.ContentType>>> (Optional)]
  Specifies how the transport listener should determine the content type of received messages.
  This can either be a simple string value, in which case the transport listener assumes that
  the received messages always have the specified content type, or a set of rules as in the following example:
  
+--------------------------------------------+
<parameter name="transport.jms.ContentType">
    <rules>
        <jmsProperty>contentType</jmsProperty>
        <jmsProperty>ctype</jmsProperty>
        <default>text/xml</default>
    </rules>
</parameter>
+--------------------------------------------+

  The rules are evaluated in turn until the first matches. The following rule types are defined:
    
    [<<<jmsProperty>>>]
    Extract the content type from the specified message property.
    
    [<<<bytesMessage>>>\
    <<<textMessage>>>]
    Match the corresponding message type. The content type is specified as the value of
    the rule, e.g. <<<\<bytesMessage\>binary/octet-stream\</bytesMessage\>>>>
    
    [<<<default>>>]
    Defines the default content type. This rule always matches and should therefore
    be the last rule in the rule set.
                    
  If none of the rules matches, an error is triggered and the message is not processed.
  The default value for this property corresponds to the following set of rules:
  
+--------------------------------------------+
<parameter name="transport.jms.ContentType">
    <rules>
        <jmsProperty>Content-Type</jmsProperty>
        <bytesMessage>application/octet-stream</bytesMessage>
        <textMessage>text/plain</textMessage>
    </rules>
</parameter>
+--------------------------------------------+

  This choice preserves compatibility with previous versions of the JMS transport. Note however
  that <<<Content-Type>>> is not a valid JMS property name and will not work with some JMS providers.
  
  [<<<Wrapper>>> (Optional)]
  The wrapper element for pure text or binary messages. Note that this parameter is
  actually not JMS specific but recognized by the message builders for <<<text/plain>>> and
  <<<application/octet-stream>>> (which are the respective default content types for JMS text
  and binary messages).
  
  []
  
  Sample <<<services.xml>>>:
  
+--------------------------------------------+
<service name="echo">
        <transports>
                ....
            <transport>jms</transport>
        </transports>
    ...
    <parameter name="transport.jms.ConnectionFactory" locked="true">myTopicConnectionFactory</parameter>
    <parameter name="transport.jms.Destination" locked="true">dynamicTopics/something.TestTopic</parameter>
</service>
+--------------------------------------------+

** {Message context properties for incoming messages}

  For incoming messages, the transport listener will make the following properties available in
  the message context:
  
    [<<<TRANSPORT_HEADERS>>>]
    This property will contain a map with the JMS message properties.

* {Transport sender}

** {Endpoint references}

  Endpoint references for the JMS transport must have the following form:
  
+--------------------------------------------+
jms-epr = "jms:/" jms-dest [ "?" param  *( [ "&" param ] ) ]
param = param-name "=" param-value
+--------------------------------------------+

  <<<jms-dest>>> is the JNDI name of the destination to send the message to. The parameters are
  defined as follows:

    [<<<transport.jms.ConnectionFactory>>> (Optional)]
    The JMS connection factory definition (from <<<axis2.xml>>>) to be used to send messages to
    the endpoint.
  
    [<<<transport.jms.ContentTypeProperty>>>]
    The name of the message property to store the content type of messages sent to the endpoint.
  
 All the above listed parameters under the connection factory configuration are applied to the JMS EPR as well, apart from these.
  
  If no connection factory definition is explicitly specified using the
  <<<transport.jms.ConnectionFactory>>> parameter, the JMS sender will check if the transport
  configuration contains a connection factory compatible with the other settings specified in the
  endpoint URL (<<<transport.jms.ConnectionFactoryJNDIName>>>, <<<java.naming.factory.initial>>>,
  <<<java.naming.provider.url>>>, <<<java.naming.security.principal>>> and
  <<<java.naming.security.credentials>>>). If a matching configuration is found, the
  sender will reuse the cached JMS objects related to that configuration. Otherwise it will
  execute the JNDI lookup and open a new connection. In that case the connection will be closed
  immediately after sending the message.
  
** {Message context properties for outcoming messages}

  For outgoing messages, the transport sender will recognize the following message context
  properties:
  
    [<<<TRANSPORT_HEADERS>>>]
    The transport expects a map as value for this property. The entries of this map will be
    set as properties on the outgoing JMS message.

  Note that all the properties are optional.
  
* {Content type detection}

  [Incoming requests]
  The content type of the message is determined according to the settings specified in
  the <<<transport.jms.ContentType>>> service parameter.
  
  [Outgoing responses]
  If the content type of the request was determined using the value of a message property, the
  content type of the response will stored in the same message property.
  
  [Outgoing requests]
  The content type will be stored in the message property specified by
  the <<<transport.jms.ContentTypeProperty>>> message context property or
  the <<<transport.jms.ContentTypeProperty>>> parameter of the endpoint reference.
  
  [Incoming responses]
  The content type will be extracted from the message property that was used to
  store the content type of the outgoing request.
