Running the Synapse Samples
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.
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
- SimpleStockQuoteService - This service has two operations, getQuote
(in/out) and placeOrder (in-only). It will generate a sample stock quote
for a given symbol.
- SimpleStockQuoteService1 - This has the same functionality as the
SimpleStockQuoteService service, but exists to make available a different
service instance/EPR to demonstrating routing
- SecureStockQuoteService1 - Simple stock quote service using WS-Security
with timestamps and username token authentication
- SecureStockQuoteService3 - Stock quote service using WS-Security
signatures and encryption
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
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.
<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:
- Smart Client mode
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.
- Synapse as a Proxy
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.
- Dumb Client
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
<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.
<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.
<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.
<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.
<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.
<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.
<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)
<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.
<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.
<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
<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.
<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.
<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
<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.
<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.
<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
<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>
<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"/>
<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&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.
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.
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.
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.
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)
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.
<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.
<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.
<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.