Use callout mediator within a fault sequence?
Reference: Multiple endpoints and conditionals?
I have sequences setup on a proxy that change the payload, and send to a service for validation (schema validation not possible). If the message is deemed valid, it is then sent to JMS. If not, a soap fault is returned to the original caller. If the JMS service is down, I need to pass the request to a third service to process the message.
If I try to use a callout mediator within the fault sequence, it looks like the mediator is not initialized (synapsecontext). I get a stacktrace as follows:
ERROR CalloutMediator Error invoking service : http://localhost:8280/soap/BypassJMS with action : urn:BypassJMS
java.lang.NullPointerException
at org.apache.synapse.mediators.builtin.CalloutMediator.mediate(CalloutMediator.java:100)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:58)
at org.apache.synapse.mediators.filters.FilterMediator.mediate(FilterMediator.java:95)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:58)
at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:125)
at org.apache.synapse.mediators.MediatorFaultHandler.onFault(MediatorFaultHandler.java:79)
at org.apache.synapse.FaultHandler.handleFault(FaultHandler.java:94)
at org.apache.synapse.core.axis2.ProxyServiceMessageReceiver.receive(ProxyServiceMessageReceiver.java:187)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:170)
at org.apache.axis2.transport.http.HTTPTransportUtils.processHTTPPostRequest(HTTPTransportUtils.java:275)
at org.apache.synapse.transport.nhttp.ServerWorker.processPost(ServerWorker.java:244)
at org.apache.synapse.transport.nhttp.ServerWorker.run(ServerWorker.java:185)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
At first I thought that maybe mediators inside of a filter weren't recursively initialized, but that can be ruled out because the in sequence does the same thing successfully.
A psuedo-code version of the proxy looks like this
<proxy>
<target>
<inSequence>
<script>alter payload</script>
<callout serviceURL="to validate"><source /><target /></callout>
<filter to check response from callout>
<then>
<script>restore payload</script>
<callout serviceURL="to send to jms"><source /><target /></callout>
<!-- above will send to fault sequence because no response -->
</then>
<else>
<script>Get and cleanup error message</script>
<makefault />
<property name="response" value="true"/>
<header name="to" action="remove" />
<send />
</else>
</filter>
</inSequence>
<outSequence>
<send />
</outSequence>
<faultSequence>
<script>
Determine if faulting because of validation, or JMS
If error invoking service of type jms:/
(we know validation successful)
If due to error creating connection (ActiveMQ was down before call)
then Set property to bypass storing on queue
else if due to error creating a producer or sending (ActiveMQ was down before call)
then Set proprety to bypass storing on queue
else if due to error JMSException: Connection reset (ActiveMQ died after call began)
then set property to bypass storing on queue
else if due to input stream for incoming message is null (ActiveMQ has no response, and this is a timeout)
then set payload to indicate message validated and sent to queue for processing
else (some other jms error)
set property to make fault
end if
else
If error invoking service of type http://
if error related to Validate callout
then set property to make fault and message indicating validation error.
else if error related to bypassing jms
then set property to make fault and message indicating processing error.
else (unrecognized error)
then set property to make fault and message of unhandled error.
end if
else
(all other errors)
set property to make fault, and dump the error_detail
</script>
<filter make fault?>
<makefault />
</filter>
<filter bypassing jms?>
<callout serviceURL="bypassjms">
<script>
set payload to indicate message validated and processed
</script>
</filter>
<send>
</faultSequence>
</target>
</proxy>
I've attached my synapse.xml and source for test client (validatedcheckin.java) and modified ant file (build.xml of axis2client samples. This requires ActiveMQ, and the synapse.xml includes additional proxies to emulate calling webservice on another server. Transports for JMS sender need to be enabled in axis2.xml but otherwise, should be default setup. Can test by loading ActiveMQ, then ESB, then stopping ActiveMQ and running test client (ant validatedcheckin)
-Lucas
| Attachment | Size |
|---|---|
| synapse.xml | 24.89 KB |
| validatedcheckin.java_.txt | 4.4 KB |
| build.xml | 10.51 KB |
- Login or register to post comments
- Printer friendly version
- 167 reads











I've discovered a workaround
I believe I have found the cause of this, and I've got a workaround. In the org.apache.synapse.config.SynapseConfiguration, on lines 819-828, the target inline sequences of each proxy is initialized for the In sequences, and Out sequences only
// initialize all the proxy services for (ProxyService p : getProxyServices()) { if (p.getTargetInLineInSequence() != null) { p.getTargetInLineInSequence().init(se); } if (p.getTargetInLineOutSequence() != null) { p.getTargetInLineOutSequence().init(se); } }This means that my fault sequence doesn't have its mediators initialized, which is why the synapse context is null when it attempts to set options within the CalloutMediator (line 100).
Thankfully, I found that I can work around this for now by putting my fault sequence as a named sequence referenced in my target, which is initialized in SynapseConfiguration on lines 830-835
// initialize managed mediators for (SequenceMediator seq : getDefinedSequences().values()) { if (seq != null) { seq.init(se); } }So now it's working well enough, but I have to be curious.. why are fault sequences not initialized in the same manner? My instincts have me believe that fault sequences may have been added later, and this block of code not updated for the initialization. On the other hand, there may be some reason for them not to be initialized. Any thoughts?
Index: modules/core/src/main/java/org/apache/synapse/config/SynapseConfiguration.java =================================================================== --- modules/core/src/main/java/org/apache/synapse/config/SynapseConfiguration.java (revision 688865) +++ modules/core/src/main/java/org/apache/synapse/config/SynapseConfiguration.java (working copy) @@ -825,6 +825,10 @@ if (p.getTargetInLineOutSequence() != null) { p.getTargetInLineOutSequence().init(se); } + + if (p.getTargetInLineFaultSequence() != null) { + p.getTargetInLineFaultSequence().init(se); + } } // initialize managed mediators-Lucas
Hi Lucas, There is no reason
Hi Lucas,
There is no reason for the inline fault sequence to not to be initialized with the proxy service, and this is purely a BUG. You may report this issue in to the Synapse JIRA [1] with the suggested patch. I will fix it. I wonder how this is being missed....
Sorry for the inconveniences.
[1] - https://issues.apache.org/jira/browse/SYNAPSE
Thanks,
Ruwan Linton