In this post I am not going to explain
about message store or message processor and their behavior. I will
exactly explain how to test SOAP Fault Data in WSO2 ESB and JMS
message store, a message processor with a reply sequence and a fault
sequence.
Before you try out
this sample, it is better to read the following articles and blog
posts to get more information.
- To read more on WSO ESB : http://wso2.com/products/enterprise-service-bus/
- Product Documentation : http://docs.wso2.org/wiki/display/ESB460/Enterprise+Service+Bus+Documentation
- Message Store : http://docs.wso2.org/wiki/display/ESB460/Message+Stores
- JMS Message Stores : http://docs.wso2.org/wiki/display/ESB460/JMS+Message+Store
- Message processor : http://docs.wso2.org/wiki/display/ESB460/Message+Processors
- Mediators : http://docs.wso2.org/wiki/display/ESB460/Mediators
- Samples on Forward Mesaging patterns with Message Stores and processors : http://docs.wso2.org/wiki/display/ESB460/Store+and+Forward+Messaging+Patterns+with+Message+Stores+and+Processors
- Error Codes : http://docs.wso2.org/wiki/display/ESB460/Error+Handling+and+Error+Codes
- Blogs : http://techfeast-hiranya.blogspot.com/2012/01/wso2-esb-tips-tricks-08-message-stores.html and http://maharachchi.blogspot.com/2012/09/now-you-can-send-soapfaults-to-fault.html
- Behaviour : https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbxKydMUlsUcTyFfMyUqeMps2pWqBhVnt-NP6Tn7zWYsQGOv1Wc0kl5-7Ha64B5iaqtYGXP92t1yLGFFTCJrplWNesVJCEkBgxDShrSjd84XwC6eW1HEYu6ptgMzPMFLGcC82Y2C-nisTI/s1600/dlc.png
- Applications and networks can be full of errors, Applications crash. Network routers and links get into states where they cannot pass messages through with the expected efficiency. These error conditions are very likely to cause a fault or trigger a runtime exception in the ESB.
- When applications and networks can be full of errors. Applications crash. Network routers and links get into states where they cannot pass messages through with the expected efficiency. These error conditions are very likely to cause a fault or trigger a runtime exception in the ESB.
- It is not mandatory to associate each sequence and proxy service with a fault sequence. In situations where a fault sequence is not specified explicitly, a default fault sequence will be used to handle errors.
Whenever
an error occurs in WSO2 ESB, the mediation engine attempts to provide
as much information as possible on the error to the user by
initializing the following properties on the erroneous message:
- ERROR_CODE
- ERROR_MESSAGE
- ERROR_DETAIL
- ERROR_EXCEPTION etc
We can configure a message broker to
save the failed requests in a message store for later delivery. When
the client
sends requests to a proxy service , the proxy service stores the
messages to a JMS message store if it cannot be delivered and then
the back-end service is invoked by a message forwarding processor,
which picks stored messages in the JMS message store.
To
test this scenario we need the following:
- Message Broker – I will be using WSO2 Message Broker (MB)
- WSO2 ESB
- WSO2 Application Server to invoke a service – Axis2Service (You can use any other service which will generate an exception)
To configure WSO2 ESB, AS and MB, follow the steps below:
- Follow the steps in the following location. http://docs.wso2.org/wiki/display/ESB460/Configure+with+WSO2+Message+Broker
- Or 1 and 2 steps in http://sandapa.blogspot.com/2013/02/jms-messaging-with-wso2-esb-460-and.html
- Now the ESB and Message broker should be ready.
Configurations :
---------------------------
- Set the offset as 2 in carbon.xml (<AS_HOME/repository/conf>) and start the Application server deploying the Axis2service. Refer the following document. http://docs.wso2.org/wiki/display/AS510/Installation+Guide
- Create a proxy. Provide the following synapse configuration.
<proxy name="FaultTestProxy"
transports="https http"
startOnLoad="true"
trace="disable">
<description/>
<target>
<inSequence>
<log level="full"/>
<property name="target.endpoint" value="AxisEp"/>
<property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
<property name="FORCE_ERROR_ON_SOAP_FAULT" value="true"/>
<store messageStore="Queue1"/>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence>
<log level="full" category="ERROR"/>
</faultSequence>
</target>
</proxy>
6. Set the endpoint as following to invoke Axis2Service. This can be any service which will help to produce an error.
<endpoint name="AxisEp">
<address uri="http://localhost:9765/services/Axis2Service">
<suspendOnFailure>
<errorCodes>-1</errorCodes>
<progressionFactor>1.0</progressionFactor>
</suspendOnFailure>
</address>
</endpoint>
7.
Create
a message store as following.
<messageStore class="org.wso2.carbon.message.store.persistence.jms.JMSMessageStore"
name="Queue1">
<parameter name="java.naming.factory.initial">org.wso2.andes.jndi.PropertiesFileInitialContextFactory</parameter>
<parameter name="store.jms.cache.connection">false</parameter>
<parameter name="java.naming.provider.url">repository/conf/jndi.properties</parameter>
<parameter name="store.jms.JMSSpecVersion">1.1</parameter>
<parameter name="store.jms.destination">Queue1</parameter>
</messageStore>
8.
Create
a Scheduled Message Forwarding Processor as following.
<messageProcessor class="org.apache.synapse.message.processors.forward.ScheduledMessageForwardingProcessor"
name="MyMsgProc"
messageStore="Queue1">
<parameter name="message.processor.reply.sequence">Axis_Ok</parameter>
<parameter name="max.delivery.attempts">4</parameter>
<parameter name="interval">5000</parameter>
<parameter name="message.processor.fault.sequence">Axis_Fault</parameter>
</messageProcessor>
9.
Following fault
sequence should be configured
<sequence name="Axis_Fault">
<log level="custom" category="ERROR">
<property name="text" value="An error occured"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="ERROR_MESSAGE"
expression="get-property('ERROR_MESSAGE')"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="ERROR_CODE"
expression="get-property('ERROR_CODE')"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="ERROR_DETAIL"
expression="get-property('ERROR_DETAIL')"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="ERROR_EXCEPTION"
expression="get-property('ERROR_EXCEPTION')"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="FaultTo"
expression="get-property('FaultTo')"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="FAULT"
expression="get-property('FAULT')"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="SENDING_FAULT"
expression="get-property('SENDING_FAULT')"/>
<property xmlns:ns="http://org.apache.synapse/xsd" name="REPLY" expression="/"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="RESPONSE"
expression="get-property('RESPONSE ')"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="HTTP_SC"
expression="get-property('HTTP_SC')"/>
</log>
<log level="full" category="ERROR"/>
</sequence>
The whole Synapse Configuration would be as follows :
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://ws.apache.org/ns/synapse">
<registry provider="org.wso2.carbon.mediation.registry.WSO2Registry">
<parameter name="cachableDuration">15000</parameter>
</registry>
#######################
# Proxy
#######################
<proxy name="FaultTestProxy"
transports="https http"
startOnLoad="true"
trace="disable">
<description/>
<target>
<inSequence>
<log level="full"/>
<property name="target.endpoint" value="AxisEp"/>
<property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
<property name="FORCE_ERROR_ON_SOAP_FAULT" value="true"/>
<store messageStore="Queue1"/>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence>
<log level="full" category="ERROR"/>
</faultSequence>
</target>
</proxy>
#######################
# Endpoint
#######################
<endpoint name="AxisEp">
<address uri="http://localhost:9765/services/Axis2Service">
<suspendOnFailure>
<errorCodes>-1</errorCodes>
<progressionFactor>1.0</progressionFactor>
</suspendOnFailure>
</address>
</endpoint>
#######################
# Fault Sequence
#######################
<sequence name="Axis_Fault">
<log level="custom" category="ERROR">
<property name="text" value="An error occured"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="ERROR_MESSAGE"
expression="get-property('ERROR_MESSAGE')"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="ERROR_CODE"
expression="get-property('ERROR_CODE')"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="ERROR_DETAIL"
expression="get-property('ERROR_DETAIL')"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="ERROR_EXCEPTION"
expression="get-property('ERROR_EXCEPTION')"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="FaultTo"
expression="get-property('FaultTo')"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="FAULT"
expression="get-property('FAULT')"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="SENDING_FAULT"
expression="get-property('SENDING_FAULT')"/>
<property xmlns:ns="http://org.apache.synapse/xsd" name="REPLY" expression="/"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="RESPONSE"
expression="get-property('RESPONSE ')"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="HTTP_SC"
expression="get-property('HTTP_SC')"/>
</log>
<log level="full" category="ERROR"/>
</sequence>
<sequence name="main">
<in>
<log level="full"/>
<filter source="get-property('To')" regex="http://localhost:9000.*">
<send/>
</filter>
</in>
<out>
<send/>
</out>
<description>The main sequence for the message mediation</description>
</sequence>
#######################
# Message Store
#######################
<messageStore class="org.wso2.carbon.message.store.persistence.jms.JMSMessageStore"
name="Queue1">
<parameter name="java.naming.factory.initial">org.wso2.andes.jndi.PropertiesFileInitialContextFactory</parameter>
<parameter name="store.jms.cache.connection">false</parameter>
<parameter name="java.naming.provider.url">repository/conf/jndi.properties</parameter>
<parameter name="store.jms.JMSSpecVersion">1.1</parameter>
<parameter name="store.jms.destination">Queue1</parameter>
</messageStore>
#######################
# Message Processor
#######################
<messageProcessor class="org.apache.synapse.message.processors.forward.ScheduledMessageForwardingProcessor"
name="MyMsgProc"
messageStore="Queue1">
<parameter name="message.processor.reply.sequence">Axis_Ok</parameter>
<parameter name="max.delivery.attempts">4</parameter>
<parameter name="interval">5000</parameter>
<parameter name="message.processor.fault.sequence">Axis_Fault</parameter>
</messageProcessor>
</definitions>
To Test:
------------
1. Via SOAP create a new SOAP project and provide the following wsdl URL,
http://localhost:8281/services/FaultTestProxy?wsdl
2. Then stop the Axis2Service and send the following request in echoInt method. (We are sending a String value except an int value)
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.carbon.wso2.org">
<soapenv:Header/>
<soapenv:Body>
<ser:echoInt>
<!--Optional:-->
<ser:x>String</ser:x>
</ser:echoInt>
</soapenv:Body>
</soapenv:Envelope>
3. Then the message store will store the message. Then start the Axis2Service. Then the Message Processor will pick the message and try to forward it. Due to the string value, following Error codes will be printed in the ESB Server console.
ERROR - LogMediator text = An error occured, ERROR_MESSAGE = Invalid value "String" for element x, ERROR_CODE = Client, ERROR_DETAIL = , ERROR_EXCEPTION = , FaultTo = , FAULT = TRUE, SENDING_FAULT = null, REPLY = <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header><ns:BAMEvent xmlns:ns="http://wso2.org/ns/2010/10/bam" activityID="13320046414250_138"/></soapenv:Header><soapenv:Body><soapenv:Fault xmlns:axis2ns26="http://schemas.xmlsoap.org/soap/envelope/"><faultcode>axis2ns26:Client</faultcode><faultstring>Invalid value "String" for element x</faultstring><detail/></soapenv:Fault></soapenv:Body></soapenv:Envelope>, RESPONSE = null, HTTP_SC = 500
This was done with the great help provided by Charitha Kankanamge. :)