Running the Synapse Samples

Contents

Overview

To run the samples bundled with the Synapse distribution you will need Ant 1.5 or later. Ant can be downloaded from http://ant.apache.org. The samples now come with a built in Axis2 server to host the service endpoints used in the samples, along with simple ant scripts to build and deploy the services into this Axis2 instance.

Starting the Axis2 Server

To start the bundled Axis2 server, go to the samples/axis2Server directory and execute the axis2server.sh or axis2server.bat script. This starts the Axis2 server with the HTTP transport listener on port 9000.

Please note that the script picks up the correct config from the AXIS2_HOME directory, so please ensure this isn't set, or points to the samples/axis2Server directory.

The sample services are available in the samples/axis2Server/src directory. To deploy these services go the the selected directory and run 'ant'. This will build the service archive file (aar) and deploy it into the Axis2 server. (i.e. copy it to the samples/axis2Server/repository\services)

For example, to deploy the SimpleStockQuoteService service go to the samples/axis2Server/src/SimpleStockQuoteService and execute 'ant' without any arguments as follows:

C:\Java\synapse\samples\axis2Server\src\SimpleStockQuoteService>ant
Buildfile: build.xml ... [jar] Building jar: C:\Java\synapse\samples\axis2Server\repository\services\SimpleStockQuoteService.aar BUILD SUCCESSFUL

Descriptions of sample Services

  1. SimpleStockQuoteService - This service has two operations, getQuote (in/out) and placeOrder (in-only). It will generate a sample stock quote for a given symbol.
  2. SimpleStockQuoteService1 - This has the same functionality as the SimpleStockQuoteService service, but exists to make available a different service instance/EPR to demonstrating routing
  3. SecureStockQuoteService1 - Simple stock quote service using WS-Security with timestamps and username token authentication
  4. SecureStockQuoteService3 - Stock quote service using WS-Security signatures and encryption

Starting Synapse

To start Synapse with the default configuration execute the synapse.bat or synapse.sh script in the bin directory. This starts up an instance of Synapse using the Synapse and Axis2 configuration files located at repository/conf

To start specific sample configurations of Synapse, use the -sample <number> switch as follows:

bin\synapse.bat -sample <number>

The above on a Windows system will use the sample synapse.xml configuration file located at repository\conf\sample\synapse_sample_<number>.xml

Invoking the sample clients

The clients are located in the samples/axis2Client directory, and should be executed with the ant script supplied. (e.g. ant stockquote) The ant script expects an argument to select the client scenario to be executed. The samples/axis2Client/client_repo directory contains an Axis2 client repository along with the necessary modules and dependencies to make available WS-Addressing, WS-Security (Rampart) and WS-Reliable Messaging (Sandesha2) on the client side.

Message Mediation Samples

Sample 0:

<synapse xmlns="http://ws.apache.org/ns/synapse">
    <!-- simple Synapse configuration -->
    <rules>
        <!-- log all attributes of messages passing through -->
        <log level="full"/>

        <!-- Send the messages where they are destined to (i.e. the 'To' EPR of the message) -->
        <send/>

        <!-- a send or drop mediator [currently] terminates further processing of the current message -->
        <!-- hence the following mediatior will not be invoked on any message -->
        <log level="custom">
            <!-- the log mediator allows custom attributes/properties for a log message. -->
            <property name="message" value="You should not see this"/>
        </log>
    </rules>
</synapse> 

Objective: Introduction to Synapse. Shows how a message could be made to pass through Synapse and logged before it is delivered to its ultimate receiver.

A client could interact with Synapse in one of three modes as follows:

  1. Smart Client mode
  2. In this mode, the client addresses its messages to the ultimate receiver of the message using WS-Addressing, but specifies the transport URL to Synapse. This results in the messages reaching Synapse with the WS-Addressing information which could be used to route the message as appropriate.

  3. Synapse as a Proxy
  4. In this mode, the client sets Synapse as an HTTP Proxy but sets the destination EPR to indicate the ultimate receiver of the message. This forces all outgoing HTTP messages to flow into Synapse, which will then send the messages as appropriate.

  5. Dumb Client
  6. In this mode, the client expects Synapse to decide on the destination of the message through appropriate routing rules using the content of the message.

Pre-Requisites:
Start the Synapse configuration numbered 0: i.e. synapse -sample 0
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

Execute the Smart Client as 'ant stockquote'
Client: samples.userguide.StockQuoteClient

If you follow through the execution of Synapse mediation rules while looking at the configuration used synapse_sample_0.xml you will notice that the client request arrived at Synapse with a WS-Addressing 'To' EPR of http://localhost:9000/axis2/services/SimpleStockQuoteService

The Synapse configuration logs the message at the highest log level as the configuration specifies the log level as 'full'. Then Synapse sends the message using the implicit 'To' address of the message - which is http://localhost:9000/axis2/services/SimpleStockQuoteService

Then you will see on the Axis2 server console, a message similar to the following

Sat Nov 18 21:01:23 IST 2006 SimpleStockQuoteService :: Generating quote for : IBM

This shows that Synapse forwarded the message to the intended recepient after logging the message and then the actual service received and processed it. The response message generated is again received at Synapse, and flows through the same mediation rules, which logs the message and then sends it - this time back to the client.

On the client console you should see an output similar to the following based on the message received by the client.

Standard :: Stock price = $95.26454380258552

Execute the Proxy client as 'ant proxystockquote'
Client: samples.userguide.ProxyStockQuoteClient

You will see the exact same behaviour as per the previous example when you run this scenario. However this time the difference is at the client and would be noticable only if one looks at the source code of the example class samples.userguide.ProxyStockQuoteClient

Sample 1:

<synapse xmlns="http://ws.apache.org/ns/synapse">
    <!-- simple content based routing of messages -->
    <rules>

        <!-- simple filtering of messages with XPath and regex matches -->
        <filter source="get-property('To')" regex=".*/StockQuote.*">

            <!-- route the message to the SimpleStockQuoteService1 service EPR -->
            <send>
                <endpoint address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>
            </send>
        </filter>

        <!-- send any other messages without change -->
        <send/>

    </rules>
</synapse> 

Objective: Introduction to simple content based routing. Shows how a message could be made to pass through Synapse using the Dumb Client mode, where Synapse acts as a gateway to accept all messages and then perform mediation and routing.

Pre-Requisites:
Start the Synapse configuration numbered 1: i.e. synapse -sample 1
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

Execute the Dumb Client as 'ant dumbstockquote'
Client: samples.userguide.DumbStockQuoteClient

This time you will notice that Synapse received a message for which Synapse was set as the ultimate receiver of the message. Based on the 'To' EPR, Synapse performed a match to the given path '/StockQuote' and as the request matched the XPath expression of the filter mediator, the filter mediators' child mediators executes, and thereby semding the message to a different endpoint as specified by the [reusable] endpoint definition.

Sample 2:

<synapse xmlns="http://ws.apache.org/ns/synapse">
    <!-- switch-case mediator and setting and reading of local properties on a message -->
    <rules>

        <!-- introduction to switch-case-default mediator -->
        <switch source="//m0:getQuote/m0:request/m0:symbol" xmlns:m0="http://services.samples/xsd">
            <case regex="IBM">
                <!-- the set-property sets a local property on the current message-->
                <!-- its value could be set as a static string as follows -->
                <set-property name="symbol" value="Great stock - IBM"/>
            </case>
            <case regex="MSFT">
                <set-property name="symbol" value="Are you sure? - MSFT"/>
            </case>
            <default>
                <!-- it is possible to assign the result of an XPath expression as the value of a message property -->
                <set-property name="symbol"
                      expression="fn:concat('Normal Stock - ', //m0:getQuote/m0:request/m0:symbol)"
                      xmlns:m0="http://services.samples/xsd"/>
            </default>
        </switch>

        <log level="custom">
            <!-- the get-property() XPath extension function allows the lookup of local message properties -->
            <property name="symbol" expression="get-property('symbol')"/>
            <!-- the get-property() function supports the implicit message headers To/From/Action/FaultTo/ReplyTo -->
            <property name="epr" expression="get-property('To')"/>
        </log>

        <!-- Send the messages where they are destined to (i.e. the 'To' EPR of the message) -->
        <send/>

    </rules>
</synapse>

Objective: Introduce switch-case mediator and writing and reading of local properties on a message

Pre-Requisites:
Start the Synapse configuration numbered 2: i.e. synapse -sample 2
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

Execute the 'ant stockquote' request again, and by following through the mediation rules executed you will see that the case statements' first case for 'IBM' executed and a local property named 'symbol' was set to 'Great stock - IBM'. Subsequently this local property value is looked up by the log mediator and logged. The message flowes through to Axis2 and then the reply back to the client.

Sample 3:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- illustration of simple properties, and reusable endpoints and sequences -->
    <definitions>

        <!-- define a string literal property -->
        <set-property name="version" value="0.1"/>

        <!-- define a reuseable endpoint definition -->
        <endpoint name="simple"
                  address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>

        <!-- define a reusable sequence -->
        <sequence name="stockquote">

            <!-- log the message using the custom log level. illustrates custom properties for log messages -->
            <log level="custom">
                <property name="Text" value="Sending quote request"/>
                <property name="version" expression="get-property('version')"/>
                <property name="symbol" expression="get-property('symbol')"/>
            </log>

            <!-- send message to real endpoint referenced by name "stockquote" endpoint definition -->
            <send>
                <endpoint ref="simple"/>
            </send>
        </sequence>
    </definitions>

    <rules>

        <!-- match the 'To' EPR to the given regex -->
        <filter source="get-property('To')" regex=".*/SimpleStockQuoteService.*">

            <!-- set a custom local message property based on the stock code requested -->
            <switch source="//m0:getQuote/m0:request/m0:symbol"
                    xmlns:m0="http://services.samples/xsd">
                <case regex="IBM">
                    <set-property name="symbol" value="Great stock - IBM"/>
                </case>
                <case regex="MSFT">
                    <set-property name="symbol" value="Are you sure? - MSFT"/>
                </case>
                <default>
                    <!-- it is possible to assign the result of an XPath expression as the value of a local message property -->
                    <set-property name="symbol"
                                  expression="fn:concat('Normal Stock - ', //m0:getQuote/m0:request/m0:symbol)"
                                  xmlns:m0="http://services.samples/xsd"/>
                </default>
            </switch>

            <!-- invoke an already defined [reusable] sequence at this point -->
            <sequence ref="stockquote"/>
        </filter>

        <!-- Log all messages passing through -->
        <log level="full"/>

        <!-- Send the messages where they have been sent (i.e. implicit To EPR) -->
        <send/>

    </rules>
</synapse> 

Objective: Illustrates simple properties, and reusable endpoints and sequences

Pre-Requisites:
Start the Synapse configuration numbered 3: i.e. synapse -sample 3
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

Execute the 'ant stockquote' request again. Following through the mediation logs you will see that once the filter and switch statments are through, the sequence named 'stockquote' is referenced and invoked. Also the log mediator dumps a string property, and two XPath evaluation results. The first expression fetches a local static string lieral property named 'version'. This is a global property applicable to all messages passing through Synapse, and available for reading from any reusable sequence or the main rules. The second expression fetches the local message property named 'symbol' which was set within the switch mediator, using the set-property mediator. However, for both expressions the 'get-property()' XPath extension function has been used. This function will first look for a given property within the local message, and if a property with the name cannot be found, it performs a lookup over all global properties. In addition, the get-property() function supports the special cases 'To', 'From', 'Action', 'FaultTo' and 'ReplyTo', which fetches the appropriate values from the current message context.

Sample 4:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- illustration of various mediators : try-catch-finally and makefault mediators -->
    <definitions>

        <!-- define an endpoint for the stock quote service -->
        <endpoint name="simple"
                  address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>

        <!-- define a non-existent endpoint to test error handling -->
        <endpoint name="bogus"
                  address="http://localhost:9009/axis2/services/NonExistentStockQuoteService"/>

        <!-- define a sequence to be used for error handling -->
        <sequence name="errorHandler">

            <!-- Log the error -->
            <log level="custom">
                <property name="text" value="An unexpected error occured"/>
                <property name="message" expression="get-property('ERROR_MESSAGE')"/>
                <property name="detail" expression="get-property('ERROR_DETAIL')"/>
            </log>

            <!-- create a custom fault message -->
            <makefault>
                <code value="tns:Receiver" xmlns:tns="http://www.w3.org/2003/05/soap-envelope"/>
                <reason expression="get-property('ERROR_MESSAGE')"/>
            </makefault>

            <send/>
        </sequence>
    </definitions>

    <rules>

        <try>
            <sequence>
                <switch source="//m0:getQuote/m0:request/m0:symbol"
                        xmlns:m0="http://services.samples/xsd">
                    <case regex="IBM">
                        <send>
                            <endpoint ref="simple"/>
                        </send>
                    </case>
                    <case regex="MSFT">
                        <send>
                            <endpoint ref="bogus"/>
                        </send>
                    </case>
                </switch>
            </sequence>
            <onError>
                <sequence ref="errorHandler"/>
            </onError>
            <finally>
                <log level="custom">
                    <property name="message" value="Processed request"/>
                </log>
            </finally>
        </try>

        <send/>

    </rules>
</synapse> 

Objective: Introduction to error handling with the try and makefault mediators

Pre-Requisites:
Start the Synapse configuration numbered 4: i.e. synapse -sample 4
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

When you execute 'ant stockquote', the default stock symbol queried is 'IBM'. However you could use the 'symbol' system property and pass it into the above (e.g. ant stockquote -Dsymbol=MSFT) to query another symbol.

When the IBM stock quote is requested, the configuration routes it to the endpoint defined as the 'simple' endpoint, which routes the message to the SimpleStockQuoteService on the local Axis2 instance. Hence a valid response message is shown at the client.

If you lookup a stock quote for 'MSFT', Synapse is instructed to route the message to the endpoint defined as the 'bogus' endpoint, which tries to deliver the message to a non existing service. Hence the method encounters a connection exception, which gets handled by the enclosing try mediator. When an error is encountered within the scope of a try mediator, it executes the mediation logic specified in its 'onError' segment. In this example, the sequence named 'errorHandler' is invoked, and it logs the error message as well as the error detail, and then creates a custom fault message reading the property named 'ERROR_MESSAGE' which is set on the current message by the try mediator on encountering an exception. At the client end, you would see the custom SOAP fault message instead of a stock quote.

Sample 5:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- error handling within a sequence using the 'onError' sequence  -->
    <definitions>

        <!-- define an endpoint for the stock quote service -->
        <endpoint name="simple"
                  address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>

        <!-- define a non-existent endpoint to test error handling -->
        <endpoint name="bogus"
                  address="http://localhost:9009/axis2/services/NonExistentStockQuoteService"/>

        <!-- demonstrate the specification of an error handler sequence for a sequence -->
        <sequence name="stockquote" onError="errorHandler">
            <switch source="//m0:getQuote/m0:request/m0:symbol"
                    xmlns:m0="http://services.samples/xsd">
                <case regex="IBM">
                    <send>
                        <endpoint ref="simple"/>
                    </send>
                </case>
                <case regex="MSFT">
                    <send>
                        <endpoint ref="bogus"/>
                    </send>
                </case>
            </switch>
        </sequence>

        <!-- define a sequence to be used for error handling -->
        <sequence name="errorHandler">

            <!-- Log the error -->
            <log level="custom">
                <property name="text" value="An unexpected error occured"/>
                <property name="message" expression="get-property('ERROR_MESSAGE')"/>
                <property name="detail" expression="get-property('ERROR_DETAIL')"/>
            </log>

            <!-- create a custom fault message -->
            <makefault>
                <code value="tns:Receiver" xmlns:tns="http://www.w3.org/2003/05/soap-envelope"/>
                <reason expression="get-property('ERROR_MESSAGE')"/>
            </makefault>

            <send/>
        </sequence>

    </definitions>

    <rules>
        <sequence ref="stockquote"/>
        <send/>
    </rules>
</synapse> 

Objective: Introduction to error handling within a sequence using the 'onError' sequence

Pre-Requisites:
Start the Synapse configuration numbered 5: i.e. synapse -sample 5
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

This sample demonstrates the ability to assign an existing sequence as the error handling sequence of another. The 'onError' attribute of a sequence calls on the named sequence specified when an exception is encountered during the processing. You could request for IBM and MSFT quotes using the same client and experience the same behaviour from Synapse.

Sample 6:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- illustration of various mediators : header, in and out mediators -->
    <rules>
        <!-- the in mediator applies only to 'incoming' messages (requests) into synapse -->
        <in>
            <filter source="//m0:getQuote/m0:request/m0:symbol" regex="IBM"
                    xmlns:m0="http://services.samples/xsd">
                <!-- set the message header for the 'To' EPR to the supplied value -->
                <header name="To"
                        value="http://localhost:9000/axis2/services/SimpleStockQuoteService1"/>
                <send/>
            </filter>

            <!-- drop (i.e. abort processing of) any other messages -->
            <drop/>
        </in>

        <!-- the out mediator applies only to 'outgoing' messages (responses) from synapse -->
        <out>
            <!-- display a log message at the time a response passes through synapse -->
            <log level="custom">
                <property name="message" value="sending back the response"/>
            </log>

            <send/>
        </out>
    </rules>
</synapse> 

Objective: Introduction to header, in and out mediators

Pre-Requisites:
Start the Synapse configuration numbered 6: i.e. synapse -sample 6
Start the Axis2 server and deploy the SimpleStockQuoteService1 (Refer steps above)

In this example we use the same stockquote client which sets the 'To' EPR of the message to the SimpleStockQuoteService service. However, if this request is for the IBM stock, the configuration invokes the header mediator and sets the 'To' value to the SimpleStockQuoteService1. Hence if you request for the IBM stock, you should see the header mediator changing the WS-Addressing header in the log message, and on the Axis2 server console you would notice that the SimpleStockQuoteService1 service indeed received and processed the response. You will also see that the mediation rules now use the in and out mediators - which executes the mediators within them depending on whether the message is an incoming request from a client, or a response message being sent to a client from Synapse. The log message 'sending back the response' prints only during the processing of the response message.

If a request is made for any other stock, Synapse is instructed to drop the message and hence the client will not receive any response. The drop mediator aborts further processing of a message and may be used to discard and reject unwanted messages.

Sample 7:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- introduction of static inline XML properties and the validation mediator -->
    <definitions>

        <!-- define a static property for an XSD schema resource as an inline XML fragment -->
        <set-property name="validate_schema">
            <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
                       xmlns="http://www.apache-synapse.org/test" elementFormDefault="qualified"
                       attributeFormDefault="unqualified"
                       targetNamespace="http://services.samples/xsd">
                <xs:element name="getQuote">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="request">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element name="stocksymbol" type="xs:string"/>
                                    </xs:sequence>
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:schema>
        </set-property>

        <endpoint name="stockquote"
                  address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>

        <sequence name="customrequest">
            <!-- is this a valid custom request ? -->
            <validate>
                <schema key="validate_schema"/>
                <on-fail>
                    <!-- if the request does not validate againt schema throw a fault -->
                    <makefault>
                        <code value="tns:Receiver"
                              xmlns:tns="http://www.w3.org/2003/05/soap-envelope"/>
                        <reason value="Invalid custom quote request"/>
                    </makefault>

                    <!-- send the fault and stop processing -->
                    <send/>
                </on-fail>
            </validate>

            <!-- send message to real endpoint referenced by name "stockquote" and stop -->
            <send>
                <endpoint ref="stockquote"/>
            </send>
        </sequence>

    </definitions>

    <rules>
        <in>
            <!-- is this a custom stock quote message? -->
            <filter xpath="//m0:getQuote" xmlns:m0="http://services.samples/xsd">
                <sequence ref="customrequest"/>
            </filter>
        </in>

        <!-- just let the message flow through -->
        <send/>

    </rules>
</synapse> 

Objective: Introduction to the extension mediators, static XML properties and the validate mediator

Pre-Requisites:
Download Xerces2-j 2.8.0 or later, and copy the xml-apis.jar and xercesImpl.jar into the lib/endorsed folder
Start the Synapse configuration numbered 7: i.e. synapse -sample 7
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

The validate mediator is bundled as an extension mediator as it depends on the Xerces2-j parser for schema validation, to keep the core Synapse distribution compact. Hence to try this example you will first need to download the Xerces parser and place its jar files into the lib folder to make it available to the validate mediator.

This example shows how an XML fragment could be made available to Synapse as a property. Such a property is called an inline XML property and is static since its content never changes after initiation. Hence a Schema is made available to the configuration as a property named 'validate_schema'.

Synapse supports string, inline text, inline xml and URL source properties which are static properties. In addition it supports dynamic registry based properties as introduced later.

In this example the request messages are filtered using a boolean XPath expression which checks if the request is a getQuote request. If so the 'customsequence' sequence is invoked, which in-turn calls on the validate mediator passing it the property key 'validate_schema'. The validate mediator by default operates on the first child element of the SOAP body. You may specify an XPath expression using an attribute 'source' to override this behaviour. The validate mediator now uses the 'validate_schema' property to validate the incoming message, and if the message is in error invokes on the 'on-fail' sequence of mediators.

If you send a standard stockquote request using 'ant stockquote' you will now get a fault back with a message 'Invalid custom quote request' as the schema validation failed. This is because the schema used in the example expects a slightly different message than what is created by the stock quote client. (i.e. expects a 'stocksymbol' element instead of 'symbol' to specify thestock symbol)

Sample 8:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- introduction to URL source properties, registry based properties and the XSLT mediator -->

    <!-- the SimpleURLRegistry allows access to a URL based resource store such as the -->
    <!-- file system (file://) or a web server (http://) -->
    <registry provider="org.apache.synapse.registry.url.SimpleURLRegistry">
        <!-- the root property of the simple URL registry helps resolve a resource URL as root + key -->
        <property name="root" value="file:repository/conf/sample/resources/"/>
        <!-- all resources loaded from the URL registry would be cached for this number of milli seconds -->
        <property name="cachableDuration" value="15000"/>
    </registry>

    <definitions>

        <!-- define a static property for the first XSLT resource as an URL source (could be any URL src) -->
        <set-property name="xslt-key-req"
                      src="file:repository/conf/sample/resources/transform/transform.xslt"/>

        <!-- define a dynamic property for the second XSLT resource as a key reference to the registry -->
        <!-- the key is just a unique identifier for a resource on the registry. It is treated as a string literal -->
        <set-property name="xslt-key-resp" key="transform/transform_back.xslt"/>

        <!-- define a reuseable endpoint definition and use it within config -->
        <endpoint name="stockquote"
                  address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>

    </definitions>

    <rules>
        <in>
            <!-- transform the custom quote request into a standard quote requst expected by the service -->
            <xslt key="xslt-key-req"/>

            <!-- send message to real endpoint referenced by name "stockquote" and stop -->
            <send>
                <endpoint ref="stockquote"/>
            </send>
        </in>

        <out>
            <!-- transform the standard response back into the custom format the client expects -->
            <xslt key="xslt-key-resp"/>

            <!-- now send the custom response back to the client and stop -->
            <send/>
        </out>
    </rules>
</synapse> 

Objective: Introduction to URL source properties, registry based properties and the XSLT mediator

Pre-Requisites:
Download Xalan-J version 2.7.0 or later, and copy xalan.jar and serializer.jar into the Synapse lib folder. Copy xercesImpl.jar and xml-apis.jar (of Xerces-J) into the lib/endorsed folder.
Start the Synapse configuration numbered 8: i.e. synapse -sample 8
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

This example uses the XSLT mediator to perform transformations, and the xslt tranformation is specified as a property, similar to the way the a schema was specified to the validate mediator. The first resource 'xslt-key-req' is specified by specifying its URL. The URL could be any valid URL, for e.g. http://someserver/path/resource.xslt or a file:// URL etc. The second resource 'xslt-key-resp' is specified using a 'key' attribute.

In this example you will notice the new 'registry' definition. Synapse comes with a simple URL based registry called SimpleURLRegistry. During initialization of the registry, the SimpleURLRegistry expects to find a property named 'root', which specifies a prefix for the registry keys used later. When the SimpleURLRegistry is used, this root is prefixed to the property key to form the complete URL for the resource being looked up. The registry caches a resource once requested, and caches it internally for a specified duration. Once this period expires, it will reload the meta information about the resource and reload its cached copy if required, the next time the resource is requested.

Hence the second XSLT resource key 'transform/transform_back.xslt' concatenated with the 'root' of the SimpleUTLRegistry 'file:repository/conf/sample/resources/' forms the complete URL of the resource as 'file:repository/conf/sample/resources/transform/transform_back.xslt' and caches its value for a period of 15000 seconds.

Execute the custom quote client as 'ant customquote' and check analyze the the Synapse debug log output as shown below

DEBUG XSLTMediator - Transformation source :<m0:CheckPriceRequest xmlns:m0=http://www.apache-synapse.org/test>
<m0:Code>IBM</m0:Code></m0:CheckPriceRequest>
DEBUG XSLTMediator - Transformation result :
<m:getQuote xmlns:m=http://services.samples/xsd>
<m:request><m:symbol>IBM</m:symbol></m:request></m:getQuote>

The incoming message is now transformed into a standard stock quote request as expected by the SimpleStockQuoteService deployed on the local Axis2 instance by the XSLT mediator. The XSLT mediator uses Xalan-J to perform the transformations, and hence the necessary Xalan-J and Xerces-J libraries needs to be made available to Synapse. The response from the SimpleStockQuoteService is converted into the custom format as expected by the client during the out message processing.

During the response processing you could notice the SimpleURLRegistry fetching the resource as shown by the debug logs below

INFO SimpleURLRegistry - ==> Repository fetch of resource with key : transform/transform_back.xslt

If you re-run the client again immidiately (i.e within 15 seconds of the first request) you will not see the resource being re-loaded by the registry as the cached value would be still valid.

However if you leave the system idle for 15 seconds or more and then retry the same request, you will now notice that the registry noticed the cache expiry and checked the meta information about the resource to check if the resource itself has changes and requires a fresh fetch from the source URL.

DEBUG AbstractRegistry - Cached object has expired for key : transform/transransform_back.xslt
DEBUG SimpleURLRegistry - Perform RegistryEntry lookup for key : transform/transform_back.xslt
DEBUG AbstractRegistry - Expired version number is same as current version in registry
DEBUG AbstractRegistry - Renew cache lease for another 15s

Now edit the repository/conf/sample/resources/transform/transform_back.xslt file and add a blank line at the end. Now when you run the client again, and if the cache is expired, the resource would be re-fetched from its URL by the registry and this can be seen by the following debug log messages

DEBUG AbstractRegistry - Cached object has expired for key : transform/transform_back.xslt
DEBUG SimpleURLRegistry - Perform RegistryEntry lookup for key : transform/transform_back.xslt
INFO SimpleURLRegistry - ==> Repository fetch of resource with key : transform/transform_back.xslt

Thus the SimpleURLRegistry allows resource to be cached, and updates detected so that changes could be reloaded without restarting the Synapse instance.

Sample 9:

<synapse xmlns="http://ws.apache.org/ns/synapse">
    <!-- introduction dynamic sequences -->

    <registry provider="org.apache.synapse.registry.url.SimpleURLRegistry">
        <!-- the root property of the simple URL registry helps resolve a resource URL as root + key -->
        <property name="root" value="file:repository/conf/sample/resources/"/>
        <!-- all resources loaded from the URL registry would be cached for this number of milli seconds -->
        <property name="cachableDuration" value="15000"/>
    </registry>

    <definitions>
        <sequence name="dynamic_sequence" key="sequence/dynamic_seq_1.xml"/>
    </definitions>

    <rules>
        <sequence ref="dynamic_sequence"/>
    </rules>
</synapse> 

Objective: Introduction to dynamic sequences with a Registry

Pre-Requisites:
Start the Synapse configuration numbered 9: i.e. synapse -sample 9
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

This example introduces the dynamic behaviour of Synapse through the use of a Registry. Synapse supports dynamic definitions for sequences, the main rules, endpoints and as seen before resources and properties. In this example we define a Synapse configuration which references a sequence definition specified as a registry key. The registry key resolves to the actual content of the sequence which would be loaded dynamically by Synapse at runtime, and cached accordingly as per its registry definition. Once the cache expires, Synapse would recheck the meta information for the definition and re-load the sequence definition if necessary and re-cache it again.

Once Synapse is started, execute the stock quote client as 'ant stockquote'. You will notice that that Synapse fetches the definition of the sequence from the registry and executes its rules as follows:

DEBUG SequenceMediator - Sequence mediator <anonymous> :: mediate()
INFO SimpleURLRegistry - ==> Repository fetch of resource with key : sequence/dynamic_seq_1.xml
.....
INFO LogMediator - message = *** Test Message 1 ***
...

Now if you execute the client immidiately (i.e. within 15 seconds of the last execution) you will notice that the sequence was not reloaded. If you now edit the repository/conf/sample/resources/sequence/dynamic_seq_1.xml and edit the log message to read as "*** Test Message 2 ***" and execute the client again, you will notice that the new message is not yet visible (i.e. if you execute this within 15 seconds of loading the resource for the first time) However, after 15 seconds have elapsed since the original caching of the sequence, you will notice that the new sequence is loaded and executed by Synapse from the following log messages:

DEBUG SequenceMediator - Sequence mediator <anonymous> :: mediate()
DEBUG AbstractRegistry - Cached object has expired for key : sequence/dynamic_seq_1.xml
DEBUG SimpleURLRegistry - Perform RegistryEntry lookup for key : sequence/dynamic_seq_1.xml
INFO SimpleURLRegistry - ==> Repository fetch of resource with key : sequence/dynamic_seq_1.xml
...
INFO LogMediator - message = *** Test Message 2 ***
...

The cache timeout could be tuned appropriately by configuring the URL registry to suite the environment and the needs.

Sample 10:

<synapse xmlns="http://ws.apache.org/ns/synapse">
    <!-- introduction dynamic endpoints -->

    <registry provider="org.apache.synapse.registry.url.SimpleURLRegistry">
        <!-- the root property of the simple URL registry helps resolve a resource URL as root + key -->
        <property name="root" value="file:repository/conf/sample/resources/"/>
        <!-- all resources loaded from the URL registry would be cached for this number of milli seconds -->
        <property name="cachableDuration" value="15000"/>
    </registry>

    <definitions>
        <endpoint name="dynamic_endpoint" key="endpoint/dynamic_endpt_1.xml"/>
    </definitions>

    <rules>
        <in>
            <send>
                <endpoint ref="dynamic_endpoint"/>
            </send>
        </in>
        <out>
            <send/>
        </out>
    </rules>
</synapse> 

Objective: Introduction to dynamic endpoints with a Registry

Pre-Requisites:
Start the Synapse configuration numbered 10: i.e. synapse -sample 10
Start the Axis2 server and deploy the SimpleStockQuoteService and the SimpleStockQuoteervice1 (Refer steps above)

This example introduces dynamic endpoints, where the definition of an endpoint is stored in a Registry. To follow this example execute the stock quote client as 'ant stockquote' and see that the message is routed to the SimpleStockQuoteService on the Axis2 instance. Repeat the above example and notice that the endpoint is cached and reused by Synapse - similarly to example # 8.

SimpleStockQuoteService :: Generating quote for : IBM

Now edit the repository/conf/sample/resources/endpoint/dynamic_endpt_1.xml definition and update the address to "http://localhost:9000/axis2/services/SimpleStockQuoteService1". After the cached value expires, the Registry loads the new definition of the endpoint, and then the messages can be seen being routed to the SimpleStockQuoteService1.

SimpleStockQuoteService 1 :: Generating quote for : IBM

Sample 11:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- a full registry based configuration -->

    <registry provider="org.apache.synapse.registry.url.SimpleURLRegistry">
        <!-- the root property of the simple URL registry helps resolve a resource URL as root + key -->
        <property name="root" value="file:repository/conf/sample/resources/"/>
        <!-- all resources loaded from the URL registry would be cached for this number of milli seconds -->
        <property name="cachableDuration" value="15000"/>
    </registry>

</synapse> 

Objective: A full registry based configuration

Pre-Requisites:
Start the Synapse configuration numbered 11: i.e. synapse -sample 11
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

This example shows a full registry based Synapse configuration. The Synapse configuration held on a node hosting Synapse simply points to the registry and looks up the actual configuration by requesting the key ''synapse.xml'. This could be used to host a configuration on a file system or http server based registry, and allow a cluster of Synapse instances to load the configuration from this registry.

Using 'ant stockquote' you would notice that the 'synapse.xml' configuration has been loaded from the root of the Simple URL based registry.

WS-Security

Sample 50:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- Connecting to endpoints with WS-Security for outgoing messages -->
    <definitions>
    <set-property name="sec_policy" src="file:repository/conf/sample/resources/policy/policy_3.xml"/>
    
        <endpoint name="secure" address="http://localhost:9000/axis2/services/SecureStockQuoteService3">
        <enableSec policy="sec_policy"/>
        <enableAddressing/>
        </endpoint>
    </definitions>

    <rules>
    <in>
    <header name="To" value="http://localhost:9000/axis2/services/SecureStockQuoteService3"/>
        <send>
        <endpoint ref="secure"/>
        </send>
      </in>
      <out>
      <header name="wsse:Security" action="remove"
                    xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"/>
      <send/>
      </out>
    </rules>
</synapse>

Objective: Connecting to endpoints with WS-Security for outgoing messages

Pre-Requisites:
Download and copy the BouncyCastle JAR file into your Synapse lib directory. (Note: the exact JAR you need to install depends on your JDK - for JDK 1.4 I have used bcprov-jdk13-132.jar)

To use the Apache Rampart module, you would also need to ensure that Xerces has been made available in the Synapse lib directory (e.g. xercesImpl-2.8.1.jar). You may also need the unlimited strength JDK policy files for your JDK to be installed (e.g. see http://java.sun.com/j2se/1.4.2/download.html)

Start the Synapse configuration numbered 50: i.e. synapse -sample 50
Copy the Apache Rampart module (e.g. rampart-1.1-SNAPSHOT.mar) into the modules directory of the sample Axis2 server samples/axis2Server/repository/modules. The Rampart module could be found at repository\modules and is not duplicated within the distributions due to its large file size.
Start the Axis2 server and deploy the SecureStockQuoteService3 (Refer steps above)

Use the stock quote client to send a request without WS-Security. Synapse is configured to enable WS-Security policy 'policy_3.xml' to the outgoing message when sent to the SecureStockQuoteService3 service endpoint hosted on the Axis2 instance. The debug log messages on Synapse shows the encrypted message flowing to the service and the encrypted response being received by Synapse. The wsse:Security header is then removed from the decrypted message and the response is delivered back to the client as it expects.

Proxy services

Sample 100:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- introduction to Synapse proxy services. A web service proxy is created and
     hosted on Synapse based on the given WSDL and exposed over all available
     transports for Synapse. If a proxy service should be exposed over only a sub set
     of the available transports, use the transports attribute -->
    <definitions>
        <set-property name="proxy_wsdl" src="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl"/>
    </definitions>

    <proxies>
        <proxy name="StockQuoteProxy">
            <wsdl key="proxy_wsdl"/>
        </proxy>
    </proxies>

    <rules>
        <in>
            <send>
                <endpoint address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>
            </send>
        </in>
        <out>
            <send/>
        </out>
    </rules>

</synapse>

Objective: Introduction to Synapse proxy services

Pre-Requisites:
Start the Synapse configuration numbered 100: i.e. synapse -sample 100
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

Once Synapse starts, you could go to http://localhost:8080/axis2/services/StockQuoteProxy?wsdl and view the WSDL for the proxy service defined in the configuration. This WSDL is based on the source WSDL supplied in the proxy service definition, and is updated to reflect the proxy service EPR. If a proxy service definition does not specify a target for its messages, the Synapse mediation rules are applied to route messages.

Execute the stock quote client by requesting for a stock quote on the proxy service as follows:

ant stockquote -Durl=http://localhost:8080/axis2/services/StockQuoteProxy

You will now notice that the Synapse mediation rules were applied and the request was routed to the SimpleStockQuoteService service on the local Axis2 instance. The response message is mediated using the same rules, as an outgoing sequence is not specified in this example either. The client should receive a stock quote reply from the proxy service. Also the client could get the WSDL for the proxy service by requesting for http://localhost:8080/axis2/services/StockQuoteProxy?wsdl

Sample 101:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- using custom sequences for incoming and outgoing message mediation with proxy services -->
    <definitions>
        <set-property name="proxy_wsdl" src="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl"/>

        <sequence name="proxy_1">
            <send>
                <endpoint address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>
            </send>
        </sequence>

        <endpoint name="proxy_2_endpoint" address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>

    </definitions>

    <proxies>
        <proxy name="StockQuoteProxy1">
            <wsdl key="proxy_wsdl"/>
            <target inSequence="proxy_1"/>
        </proxy>

        <proxy name="StockQuoteProxy2">
            <wsdl key="proxy_wsdl"/>
            <target endpoint="proxy_2_endpoint"/>
        </proxy>
    </proxies>

    <rules>
        <send/>
    </rules>

</synapse>

Objective: Using custom sequences and endpoints for message mediation with proxy services

Pre-Requisites:
Start the Synapse configuration numbered 101: i.e. synapse -sample 101
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

This configuration creates two proxy services with different behaviour. The first proxy service 'StockQuoteProxy1' uses the sequence named 'proxy_1' as its main mediation sequence for messages it receives. The second proxy service 'StockQuoteProxy2' is set to directly forward messages that are received to the endpoint named 'proxy_2_endpoint' without any mediation.

You could send a stock quote request to each of these proxy services and receive the reply generated by the actual service hosted on the Axis2 instance. Use the -Durl=<EPR> property when executing the client as per example 100, to request on the two proxy services.

Sample 102:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- attaching service level WS-Security policies to proxy services -->
    <definitions>
        <set-property name="proxy_wsdl"
                      src="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl"/>
        <set-property name="sec_policy"
                      src="file:repository/conf/sample/resources/policy/policy_1.xml"/>
    </definitions>

    <proxies>
        <proxy name="StockQuoteProxy">
            <wsdl key="proxy_wsdl"/>
            <policy key="sec_policy"/>
            <enableSec/>
        </proxy>
    </proxies>

    <rules>
        <in>
            <header name="wsse:Security" action="remove"
                    xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"/>
            <send>
                <endpoint address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>
            </send>
        </in>
        <out>
            <send/>
        </out>
    </rules>

</synapse>

Objective: Attaching service level WS-Security policies to proxy services

Pre-Requisites:
Start the Synapse configuration numbered 102: i.e. synapse -sample 102

Copy the Apache Rampart module (e.g. rampart-1.1-SNAPSHOT.mar) into the modules directories of both the sample Axis2 client and server: samples/axis2Client/client_repo/modules and samples/axis2Server/repository/modules. The Rampart module could be found at repository\modules and is not duplicated in the distributions due to its large file size.

Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

To execute the sample use the stock quote client with the 'secpolicy' and 'url' system properties passed in as follows:

e.g.

ant stockquote -Durl=http://localhost:8080/axis2/services/StockQuoteProxy -Dsecpolicy=..\..\repository\conf\sample\resources\policy\policy_1.xml

The sample security policy policy_1.xml uses timestamps and username token tuhentication on the stock quote request. Following the debug logs on the Synapse server you could notice the presence of WS-Security headers on the incoming message. By requesting the WSDL of the proxy service you could also see that the supplied policy file has been attached to the specified WSDL as well.

e.g. http://localhost:8080/axis2/services/StockQuoteProxy?wsdl

A proxy service with an attached policy - such as a WS-Security policy - ensures that messages which goes through mediation have satisfied the constraints as specified by the supplied policy. i.e. for example, if any WS-Security validations fail, the message will not reach Synapse mediation, but the client would get an appropriate error message from the Apache Rampart module directly.

The mediation shows the header mediator used to strip out the wsse:Security header from the current message before being forwarded to the SimpleStockQuoteService. Hence the message sent to the stock quote service EPR is without any WS-Security headers as can be seen from the log messages.

Note: If you wish to engage the default WS-Security policy of Rampart on a proxy service, you could use the <enableSec/> option on a proxy service alone. This will be similar in function to 'engaging' Rampart on an Axis2 service.

Sample 103:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- attaching service level WS-Security policies to proxy services -->
    <definitions>
        <set-property name="proxy_wsdl"
                      src="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl"/>
        <set-property name="sec_policy"
                      src="file:repository/conf/sample/resources/policy/policy_3.xml"/>
    </definitions>

    <proxies>
        <proxy name="StockQuoteProxy">
            <wsdl key="proxy_wsdl"/>
            <policy key="sec_policy"/>
            <enableSec/>
        </proxy>
    </proxies>

    <rules>
        <in>
            <header name="wsse:Security" action="remove"
                    xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"/>
            <send>
                <endpoint address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>
            </send>
        </in>
        <out>
            <send/>
        </out>
    </rules>

</synapse>

Objective: Using WS-Security signing and encryption with proxy services through WS-Policy

Pre-Requisites:
Download and copy the BouncyCastle JAR file into your Synapse lib directory. (Note: the exact JAR you need to install depends on your JDK - for JDK 1.4 I have used bcprov-jdk13-132.jar)
Start the Synapse configuration numbered 103: i.e. synapse -sample 103
Copy the Apache Rampart module (e.g. rampart-1.1-SNAPSHOT.mar) into the modules directory of the sample Axis2 client samples/axis2Client/client_repo/modules. The Rampart module could be found at repository\modules and is not duplicated within the distributions due to its large file size.
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

To execute the sample use the dumb stock quote client with the 'secpolicy' and 'gatewayurl' system properties passed in as follows:

e.g.

ant dumbstockquote -Dsecpolicy=..\..\repository\conf\sample\resources\policy\client_policy_3.xml -Dgatewayurl=http://localhost:8080/axis2/services/StockQuoteProxy

The sample security policy client_policy_3.xml ensures signed and encrypted messages which request for the stock quotes. Following the debug logs on the Synapse server you could notice the presence of WS-Security headers on the incoming message. By requesting the WSDL of the proxy service you could also see that the supplied policy file has been attached to the specified WSDL as well.

e.g. http://localhost:8080/axis2/services/StockQuoteProxy?wsdl

By following through the Synapse log messages you could see that the proxy service received and decrypted the secured SOAP envelope. (If you sent the client request to Synapse through a TCP monitor you would be able to see the raw encrypted message in transit) and forwarded this to the simple stockquote service, and once the response was received, signed it and encrypted it before sending it back to the client.

Using TCPMon, a sample request sent from the client to the WS-Security enabled proxy service has been captured as follows: sample_103_1.txt

Synapse removes the wsse:Security header from this message and forwards it to the endpoint. The response received is now signed and encrypted and sent back to the client as follows: sample_103_2.txt

Sample 104:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- using custom sequences for incoming and outgoing message mediation with proxy services -->
    <definitions>
        <set-property name="proxy_wsdl" src="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl"/>

        <sequence name="proxy_in">
            <send>
                <endpoint address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>
            </send>
        </sequence>

        <sequence name="proxy_out">
            <log level="custom">
                <property name="message" value="Executing inside the out sequence"/>
            </log>
            <send/>
        </sequence>

    </definitions>

    <proxies>
        <proxy name="StockQuoteProxy">
            <wsdl key="proxy_wsdl"/>
            <target inSequence="proxy_in" outSequence="proxy_out"/>
        </proxy>
    </proxies>

    <rules>
        <send/>
    </rules>

</synapse>

Objective: Using an explicit out sequence in proxy service level to mediate proxy response

Pre-Requisites:
Start the Synapse configuration numbered 104: i.e. synapse -sample 104
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

This configuration creates a proxy service with the name StockQuoteProxy. This proxy service specifies both inSequence and the outSequence for that service. This will add a proxy level out sequence to be used for the response message mediation of that particular proxy service. You could leave the whole target element not specified or one of the sequences of in and out unspecified, so that the corresponding message will be mediated using main mediator.

You could send a stock quote request to this proxy services and receive the reply generated by the actual service hosted on the Axis2 instance. Use the -Durl=<EPR> property when executing the client as per example 100, to request on this proxy service.

You can observe the synapse log to see the response message mediation using the specified outSequence, unlike using MainMediator in the sample 100 case. The log should be as follows

DEBUG SequenceMediator - Sequence mediator <proxy_out> :: mediate()
DEBUG AbstractListMediator - Implicit Sequence <SequenceMediator> :: mediate()
DEBUG LogMediator - Log mediator :: mediate()
INFO  LogMediator - message = Executing inside the out sequence

Sample 105:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- demonstrate JMS raw Text / POX message support -->
    <definitions>
        <sequence name="text_proxy">
            <header name="Action" value="urn:placeOrder"/>
            <script.js><![CDATA[
               var args = mc.getPayloadXML().toString().split(" ");
               mc.setPayloadXML(
                <m:placeOrder xmlns:m="http://services.samples/xsd">
                    <m:order>
                        <m:price>{args[0]}</m:price>
                        <m:quantity>{args[1]}</m:quantity>
                        <m:symbol>{args[2]}</m:symbol>
                    </m:order>
                </m:placeOrder>);
            ]]></script.js>
            <send>
                <endpoint address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>
            </send>
        </sequence>

        <sequence name="mtom_proxy">
            <header name="Action" value="urn:uploadFileUsingMTOM"/>
            <send>
                <endpoint address="http://localhost:9000/axis2/services/MTOMSampleService" optimize="mtom"/>
            </send>
        </sequence>

        <sequence name="pox_proxy">
            <header name="Action" value="urn:placeOrder"/>
            <send>
                <endpoint address="http://localhost:9000/axis2/services/SimpleStockQuoteService" force="soap"/>
            </send>
        </sequence>
    </definitions>

    <proxies>
        <proxy name="JMSFileUploadProxy" transports="jms">
            <target inSequence="mtom_proxy"/>
            <property name="transport.jms.Wrapper" value="{http://services.samples/xsd}element"/>
        </proxy>
        <proxy name="JMSTextProxy" transports="jms">
            <target inSequence="text_proxy"/>
            <property name="transport.jms.Wrapper" value="{http://services.samples/xsd}text"/>
        </proxy>
        <proxy name="JMSPoxProxy" transports="jms">
            <target inSequence="pox_proxy"/>
        </proxy>
    </proxies>

    <rules>
    <log level="full"/>
    <drop/>
    </rules>

</synapse>

Objective: Pure POX/Text and Binary JMS Proxy services - including MTOM

Pre-Requisites:
Configure JMS for Synapse (Refer notes above)
Configure the script mediator runtime (Refer notes below)
i.e. make bsf-2.4.0.jar, xbean-2.2.0.jar and js-1.6R2.jar available in lib folder)
Configure Synapse and the sample Axis2 server to use MTOM (i.e. set enableMTOM parameter to true)
Start the Synapse configuration numbered 105: i.e. synapse -sample 105
Start the Axis2 server and deploy the SimpleStockQuoteService and the MTOMSampleService (Refer steps above)

This configuration creates three JMS proxy services named JMSFileUploadProxy, JMSTextProxy and JMSPoxProxy exposed over JMS queues with the same names. The first part of this example demonstrates the pure text message support with JMS, where a user sends a text JMS message of the form "<price> <qty> <symbol>". Synapse converts this message into a SOAP message and sends this to the SimpleStockQuoteServices' placeOrder operation. The mediation uses the script mediator to transform the text message into a XML payload. The proxy service property named "transport.jms.Wrapper" defines the wrapper element QName, to be used when wrapping text/binary content into a SOAP envelope.

Execute ' ant jmsclient -Dpayload="24.34 100 IBM"' which executes the first scenario. The client sends a JMS text message with the specified payload to the specified destination. Though the debug logs, you could see that Synapse received a text message over JMS and converted this to a SOAP message and sent it to the SimpleStockQuoteService as follows

[JMSWorker-1] DEBUG ProxyServiceMessageReceiver - Proxy Service JMSTextProxy received a new message...
[JMSWorker-1] DEBUG ProxyServiceMessageReceiver - Body :
<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header /><soapenv:Body><axis2ns3:text xmlns:axis2ns3="http://services.samples/xsd">
65.05119159089897 6079 IBM</axis2ns3:text></soapenv:Body></soapenv:Envelope>
..
[JMSWorker-1] DEBUG SendMediator - Sending message to endpoint :: name = null 
resolved address = http://localhost:9000/axis2/services/SimpleStockQuoteService
<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header /><soapenv:Body><m:placeOrder xmlns:m="http://services.samples/xsd"><m:order>
<m:price>65.05119159089897</m:price><m:quantity>6079</m:quantity><m:symbol>IBM</m:symbol></m:order></m:placeOrder></soapenv:Body></soapenv:Envelope?

The next section uses the 'ant jmsclient -Dtype=binary -Ddest=dynamicQueues/JMSFileUploadProxy -Dpayload=.\..\..\repository\conf\sample\resources\mtom\asf-logo.gif" which sends a JMS bytes message to the defined destination with the content of the payload file as its body. Synapse receives the bytes message and creates a SOAP envelope. If the axis2.xml used by Synapse enables MTOM optimization (through the 'enableMTOM' parameter), then Synapse sends an MTOM optimized message to the endpoint as follows, else it encodes the content as Base64:

POST /axis2/services/MTOMSampleService HTTP/1.1
SOAPAction: "urn:uploadFileUsingMTOM"
User-Agent: Axis2Host: 127.0.0.1
Content-Length: 8528
Content-Type: multipart/related; boundary=MIMEBoundaryurn_uuid_3FE7ADC48E69671C2211646391275465; type="application/xop+xml"; 
start="<0.urn:uuid:3FE7ADC48E69671C2211646391275466@apache.org>"; start-info="text/xml"; charset=UTF-8--MIMEBoundaryurn_uuid_3FE7ADC48E69671C2211646391275465
content-type: application/xop+xml;
 charset=UTF-8; type="text/xml";content-transfer-encoding: binarycontent-id:<0.urn:uuid:3FE7ADC48E69671C2211646391275466@apache.org>
<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>...</soapenv:Header><soapenv:Body><axis2ns2:element 
xmlns:axis2ns2="http://services.samples/xsd"><xop:Include href="cid:1.urn:uuid:3FE7ADC48E69671C2211646391275464@apache.org" xmlns:xop="http://www.w3.org/2004/08/xop/include"
 /></axis2ns2:element>
</soapenv:Body>
</soapenv:Envelope>--MIMEBoundaryurn_uuid_3FE7ADC48E69671C2211646391275465content-type: application/octet-streamcontent-transfer-encoding: binarycontent-id:
<1.urn:uuid:3FE7ADC48E69671C2211646391275464@apache.org>GIF89aƒd.... ;--MIMEBoundaryurn_uuid_3FE7ADC48E69671C2211646391275465-

The final section of this example shows a POX JMS message received by Synapse and sent to the SimpleStockQuoteService as a SOAP message. Execute this scenario as 'ant jmsclient -Dtype=xml -Ddest=dynamicQueues/JMSPoxProxy -Dpayload=MSFT' and notice that since the message received by Synapse is POX, you need to force a SOAP message out through the endpoint in-order for the SimpleStockQuoteService to properly receive its response. In this example Synapse wraps the received POX message in a SOAP envelope and processes it and routes it to the real endpoint.

// TODO - REST to WS sample

<syn:synapse xmlns:syn="http://ws.apache.org/ns/synapse">
    <syn:proxies>
        <syn:proxy name="StockQuoteProxy" startOnLoad="true"/>
    </syn:proxies>
    <syn:rules>
        <syn:in>
            <syn:header name="Action" value="urn:getQuote"/>
            <syn:send>
                <syn:endpoint force="soap" address="http://localhost:9001/axis2/services/SimpleStockQuoteService"/>
            </syn:send>
        </syn:in>
        <syn:out>
            <syn:send/>
        </syn:out>
    </syn:rules>
</syn:synapse>

Transports

Sample 110:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- attaching service level WS-Security policies to proxy services -->
    <definitions>
        <set-property name="proxy_wsdl"
                      src="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl"/>
    </definitions>

    <proxies>
        <proxy name="StockQuoteProxy" transports="jms">
            <wsdl key="proxy_wsdl"/>
        </proxy>
    </proxies>

    <rules>
        <in>
            <send>
                <endpoint address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>
            </send>
        </in>
        <out>
            <send/>
        </out>
    </rules>

</synapse>

Objective: Introduction to switching transports with proxy services

Pre-Requisites:
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)
Download, install and start a JMS server, and configure Synapse to listen on JMS (refer notes below)
Start the Synapse configuration numbered 110: i.e. synapse -sample 110
For this example we would use ActiveMQ as the JMS provider. Once ActiveMQ is installed and started you should get a message as follows:

INFO BrokerService - ActiveMQ JMS Message Broker (localhost) started

You will now need to configure the Axis2 instance used by Synapse (not the sample Axis2 server) to enable JMS support using the above provider. Refer to the Axis2 documentation on setting up JMS for more details (http://ws.apache.org/axis2/1_1/jms-transport.html). You will also need to copy the ActiveMQ client jar files activeio-core-3.0-beta1.jar, activemq-core-4.0-RC2.jar, geronimo-jms_1.1_spec-1.0.jar and geronimo-j2ee-management_1.0_spec-1.0.jar into the lib directory to allow Synapse to connect to the JMS provider.

For a default ActiveMQ v4.0 installation, you may uncomment the Axis2 transport listener configuration found at repository/conf/axis2.xml as

<transportReceiver name="jms" class="org.apache.axis2.transport.jms.JMSListener"> ...

Once you start the Synapse configuration and request for the WSDL of the proxy service you will notice that its exposed only on the JMS transport. This is because the configuration specified this requirement in the proxy service definition.

Now lets send a stock quote request on JMS, using the dumb stock quote client as follows:

ant dumbstockquote -Dgatewayurl="jms:/StockQuoteProxy?transport.jms.ConnectionFactoryJNDIName=
QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.
ActiveMQInitialContextFactory&java.naming.provider.url=tcp://localhost:61616"

On the Synapse debug log you will notice that the JMS listener received the request message as:

[JMSWorker-1] DEBUG ProxyServiceMessageReceiver -Proxy Service StockQuoteProxy received a new message...

Synapse forwarded this message to the HTTP EPR of the simple stock quote service hosted on the sample Axis2 server, and returned the reply back to the client through a JMS temporary queue.

Note: It is possible to instruct a JMS proxy service to listen to an already existing destination without creating a new one. To do this, use the property elements on the proxy service definition to specify the destination and connection factory etc.

e.g.

<property name="transport.jms.Destination" value="dynamicTopics/something.TestTopic"/>

Sample 111:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- attaching service level WS-Security policies to proxy services -->
    <definitions>
        <set-property name="proxy_wsdl"
                      src="file:repository/conf/sample/resources/proxy/sample_proxy_1.wsdl"/>
    </definitions>

    <proxies>
        <proxy name="StockQuoteProxy" transports="http">
            <wsdl key="proxy_wsdl"/>
        </proxy>
    </proxies>

    <rules>
        <in>
            <send>
                <endpoint address="jms:/SimpleStockQuoteService?transport.jms.ConnectionFactoryJNDIName=
                           QueueConnectionFactory&amp;java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&
                           amp;java.naming.provider.url=tcp://localhost:61616"/>
            </send>
        </in>
        <out>
            <send/>
        </out>
    </rules>

</synapse>

Objective: Demonstrate switching from HTTP to JMS

Pre-Requisites:
Download, install and start a JMS server, and configure Synapse to listen on JMS (refer notes below)
Configure sample Axis2 server for JMS (refer notes above)
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)
Configure JMS transport for Synapse (refer notes above - sample 110)
Start the Synapse configuration numbered 111: i.e. synapse -sample 111

To switch from HTTP to JMS, edit the samples/axis2Server/repository/conf/axis2.xml for the sample Axis2 server and enable JMS (refer notes above), and restart the server. You should now see that the simple stock quote service is available over JMS as well at an address as the one shown below, by looking at the WSDL of the service.

jms:/SimpleStockQuoteService?transport.jms.ConnectionFactoryJNDIName=
QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&
java.naming.provider.url=tcp://localhost:61616

This Synapse configuration creates a proxy service over HTTP and forwards received messages to the above EPR using JMS, and sends back the response to the client over HTTP once the simple stock quote service responds with the stock quote reply over JMS to the Synapse server.

Sample 112:

Objective: Demonstrate one way messaging / fireAndForget()

Pre-Requisites:
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)
Start the Synapse configuration numbered 1: i.e. synapse -sample 1

This example invokes the one-way 'placeOrder' operation on the SimpleStockQuoteService using the custom client which uses the Axis2 ServiceClient.fireAndForget() API. To test this, use 'ant placeorder' and you will notice the one way message flowing through Synapse into the sample Axis2 server instance, which reports the acceptance of the order as follows:

SimpleStockQuoteService :: Accepted order for : 7482 stocks of IBM at $ 169.27205579038733

If you send your client request through TCPmon, you will notice that the SimpleStockQuoteService replies to Synapse with a HTTP 202 reply, and that Synapse in-turn replies to the client with a HTTP 202 acknowledgement.

Script mediators

Synapse supports Mediators implemented in a variety of scripting languages such as JavaScript, Python or Ruby.

Implementing a Mediator with a script language can have advantages over using the built in Synapse Mediator types or implementing a custom Java class Mediator. Script Mediators have all the flexibility of a class Mediator with access to the Synapse MessageContext and SynapseEnvironment APIs, and the ease of use and dynamic nature of scripting languages allows rapid development and prototyping of custom mediators. An additional benefit of some scripting languages is that they have very simple and elegant XML manipulation capabilities, for example JavaScript E4X or Ruby REXML, so this makes them well suited for use in the Synapse mediation environment.

Configuring Synapse for Script Mediator support

The Synapse Script Mediator is a Synapse extension so all its pre-reqs are not installed by default. Before you use script mediators you need to manually add the required jars to the Synapse lib directory and do any other installation that may be required by the individual scripting languages. This is detailed in the following sections.

JavaScript support

For JavaScript/E4X support you need to copy the following jars to the Synapse lib directory:

(Note: You should be able to right click on those links and save the jars directly to your Synapse lib directory)

Ruby support

For Ruby support you need to copy the following jars to the Synapse lib directory:

(Note: You should be able to right click on those links and save the jars directly to your Synapse lib directory)

In addition to those jars, to use the REXML capabilities of Ruby requires a complete JRuby installation. Download and install JRuby from JRuby Home. Once installed you need to tell Synapse about the instalation by setting a system property when starting Synapse. Right now this requires manually editing the Synapse startup script (this will be improved in a future Synapse release). Edit the bin\synapse.bat file and at the bottom find the line starting ""%_JAVACMD%" %_SYNAPSE_XML%" and insert the system property -Djruby.home="<path to your JRuby install directory>". Note the quote characters around the JRuby directory which are required.

Sample 500:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- Introduction to the script mediator -->

    <definitions>

        <!-- define a static property for the JavaScript source code file -->
        <set-property name="stockquoteScript" src="file:repository/conf/sample/resources/script/stockquoteTransform.js"/>

        <!-- define a reuseable endpoint definition and use it within config -->
        <endpoint name="stockquote" address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>

    </definitions>

    <rules>
        <in>
            <!-- transform the custom quote request into a standard quote request expected by the service -->
            <script key="stockquoteScript" function="transformRequest"/>

            <!-- send message to real endpoint referenced by name "stockquote" and stop -->
            <send>
                <endpoint ref="stockquote"/>
            </send>
        </in>

        <out>
            <!-- transform the standard response back into the custom format the client expects -->
            <script key="stockquoteScript" function="transformResponse"/>

            <!-- now send the custom response back to the client and stop -->
            <send/>
        </out>
    </rules>

</synapse> 

Objective: Introduction to script mediators

This sample is similar to sample 8 but instead of using XSLT the transformation is done with JavaScript and E4X

The Synapse config XML for this is synapse_sample_500.xml and the associated JavaScript program is stockquoteTransform.js.

Pre-Requisites:

This sample uses JavaScript/E4X so first setup support for this in Synapse as described at Configuring JavaScript.

Start the Synapse configuration numbered 500: i.e. synapse -sample 500
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

The JavaScript script is in a separate file which the Synapse xml references by using a static property named 'stockquoteScript'. The script has two functions, 'transformRequest' and 'transformResponse', and the Synapse xml script element uses the function attribute to specify which function to use for the in and out rules.

Execute the custom quote client as 'ant customquote' and check analyze the the Synapse debug log output as shown below

DEBUG XSLTMediator - Transformation source :<m0:CheckPriceRequest xmlns:m0=http://www.apache-synapse.org/test>
<m0:Code>IBM</m0:Code></m0:CheckPriceRequest>
DEBUG XSLTMediator - Transformation result :
<m:getQuote xmlns:m=http://services.samples/xsd>
<m:request><m:symbol>IBM</m:symbol></m:request></m:getQuote>

The incoming message is now transformed into a standard stock quote request as expected by the SimpleStockQuoteService deployed on the local Axis2 instance by the JavaScript mediator. The JavaScript mediator uses E4X to perform the transformations. The response from the SimpleStockQuoteService is converted into the custom format as expected by the client during the out message processing.

Sample 501:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- Introduction to the script mediator using in-line scripts -->

    <definitions>

        <!-- define a reuseable endpoint definition and use it within config -->
        <endpoint name="stockquote" address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>

    </definitions>

    <rules>
        <in>
            <!-- transform the custom quote request into a standard quote requst expected by the service -->
            <script.js><![CDATA[
               var symbol = mc.getPayloadXML()..*::Code.toString();
               mc.setPayloadXML(
                  <m:getQuote xmlns:m="http://services.samples/xsd">
                     <m:request>
                        <m:symbol>{symbol}</m:symbol>
                     </m:request>
                  </m:getQuote>);
            ]]></script.js>

            <!-- send message to real endpoint referenced by name "stockquote" and stop -->
            <send>
                <endpoint ref="stockquote"/>
            </send>
        </in>

        <out>
            <!-- transform the standard response back into the custom format the client expects -->
            <script.js><![CDATA[
               var symbol = mc.getPayloadXML()..*::symbol.toString();
               var price = mc.getPayloadXML()..*::last.toString();
               mc.setPayloadXML(
                  <m:CheckPriceResponse xmlns:m="http://www.apache-synapse.org/test">
               <m:Code>{symbol}</m:Code>
               <m:Price>{price}</m:Price>
                  </m:CheckPriceResponse>);
            ]]></script.js>

            <!-- now send the custom response back to the client and stop -->
            <send/>
        </out>
    </rules>

</synapse> 

Objective: Introduction to in-line script mediators

This sample is the same as sample 500 but instead of having the JavaScript source defined in a separate file it is defined in-line within the Synapse XML.

The Synapse config XML for this is synapse_sample_501.xml.

Pre-Requisites:

This sample uses JavaScript/E4X so first setup support for this in Synapse as described at Configuring JavaScript.

Start the Synapse configuration numbered 501: i.e. synapse -sample 501
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

Execute the custom quote client as 'ant customquote' and check analyze the the Synapse debug log output as shown below

DEBUG XSLTMediator - Transformation source :<m0:CheckPriceRequest xmlns:m0=http://www.apache-synapse.org/test>
<m0:Code>IBM</m0:Code></m0:CheckPriceRequest>
DEBUG XSLTMediator - Transformation result :
<m:getQuote xmlns:m=http://services.samples/xsd>
<m:request><m:symbol>IBM</m:symbol></m:request></m:getQuote>

The incoming message is now transformed into a standard stock quote request as expected by the SimpleStockQuoteService deployed on the local Axis2 instance by the JavaScript mediator. The JavaScript mediator uses E4X to perform the transformations. The response from the SimpleStockQuoteService is converted into the custom format as expected by the client during the out message processing.

Sample 503:

<synapse xmlns="http://ws.apache.org/ns/synapse">

    <!-- Introduction to the script mediator with Ruby scripts-->

    <definitions>

        <!-- define a static property for the JRuby source code file -->
        <set-property name="stockquoteScript" src="file:repository/conf/sample/resources/script/stockquoteTransform.rb"/>

        <!-- define a reuseable endpoint definition and use it within config -->
        <endpoint name="stockquote" address="http://localhost:9000/axis2/services/SimpleStockQuoteService"/>

    </definitions>

    <rules>
        <in>
            <!-- transform the custom quote request into a standard quote request expected by the service -->
            <script key="stockquoteScript" function="transformRequest"/>

            <!-- send message to real endpoint referenced by name "stockquote" and stop -->
            <send>
                <endpoint ref="stockquote"/>
            </send>
        </in>

        <out>
            <!-- transform the standard response back into the custom format the client expects -->
            <script key="stockquoteScript" function="transformResponse"/>

            <!-- now send the custom response back to the client and stop -->
            <send/>
        </out>
    </rules>

</synapse> 

Objective: Script mediators using Ruby

This sample is similar to sample 500 but instead of using JavaScript the script language is Ruby using the JRuby interpreter.

The Synapse config XML for this is synapse_sample_503.xml and the associated JavaScript program is stockquoteTransform.rb.

Pre-Requisites:

This sample uses Ruby so first setup support for this in Synapse as described at Configuring JRuby.

Start the Synapse configuration numbered 503: i.e. bin/synapse -sample 503
Start the Axis2 server and deploy the SimpleStockQuoteService (Refer steps above)

The Ruby script is in a separate file which the Synapse xml references by using a static property named 'stockquoteScript'. The script has two functions, 'transformRequest' and 'transformResponse', and the Synapse xml script element uses the function attribute to specify which function to use for the in and out rules.

Execute the custom quote client as 'ant customquote' and check analyze the the Synapse debug log output as shown below

DEBUG XSLTMediator - Transformation source :<m0:CheckPriceRequest xmlns:m0=http://www.apache-synapse.org/test>
<m0:Code>IBM</m0:Code></m0:CheckPriceRequest>
DEBUG XSLTMediator - Transformation result :
<m:getQuote xmlns:m=http://services.samples/xsd>
<m:request><m:symbol>IBM</m:symbol></m:request></m:getQuote>

The incoming message is now transformed into a standard stock quote request as expected by the SimpleStockQuoteService deployed on the local Axis2 instance by the Ruby mediator. The Ruby mediator uses REXML to perform XML transformations. The response from the SimpleStockQuoteService is converted into the custom format as expected by the client during the out message processing.