I have a problem with a WSO2 proxy (ESB v5.0.0) which is secured by a Basic Authentication policy. I have created a simplified test case that shows the issue.
The Proxy service with a security policy calls a backend service which is unsecured. When this call times out, then a diagnostic response is returned to the caller via an "onError" sequence.
When the call to the backend service is made from within an iterator, then the outbound response fails with:
org.apache.axis2.AxisFault: No password supplied by the callback
handler for the user : "wso2carbon"
at org.apache.rampart.handler.RampartSender.invoke(RampartSender.java:76)
at org.apache.axis2.engine.Phase.invokeHandler(Phase.java:340)
at org.apache.axis2.engine.Phase.invoke(Phase.java:313)
at org.apache.axis2.engine.AxisEngine.invoke(AxisEngine.java:261)
at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:426)
at org.apache.synapse.core.axis2.Axis2Sender.sendBack(Axis2Sender.java:222)
at org.apache.synapse.mediators.builtin.RespondMediator.mediate(RespondMediator.java:35)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:97)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:59)
at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:158)
at org.apache.synapse.mediators.MediatorFaultHandler.onFault(MediatorFaultHandler.java:93)
at org.apache.synapse.FaultHandler.handleFault(FaultHandler.java:53)
at org.apache.synapse.endpoints.AbstractEndpoint.invokeNextFaultHandler(AbstractEndpoint.java:698)
at org.apache.synapse.endpoints.AbstractEndpoint.onFault(AbstractEndpoint.java:530)
at org.apache.synapse.endpoints.WSDLEndpoint.onFault(WSDLEndpoint.java:58)
at org.apache.synapse.FaultHandler.handleFault(FaultHandler.java:53)
at org.apache.synapse.core.axis2.TimeoutHandler.processCallbacks(TimeoutHandler.java:178)
at org.apache.synapse.core.axis2.TimeoutHandler.run(TimeoutHandler.java:89)
at java.util.TimerThread.mainLoop(Unknown Source)
at java.util.TimerThread.run(Unknown Source)
Caused by: org.apache.rampart.RampartException: No password supplied by the callback handler for the user : "wso2carbon"
at org.apache.rampart.builder.BindingBuilder.addUsernameToken(BindingBuilder.java:207)
at org.apache.rampart.builder.TransportBindingBuilder.build(TransportBindingBuilder.java:95)
at org.apache.rampart.MessageBuilder.build(MessageBuilder.java:140)
at org.apache.rampart.handler.RampartSender.invoke(RampartSender.java:65)
When the iterator is removed, the proxy completes correctly, returning my error message when the backend service times out.
If I remove the security policy then it works correctly both with and without the iterator.
Does anyone have any suggestions what might be the problem? I have simplified the proxy down to the minimum to demonstrate the error:
<proxy name="Tester" startOnLoad="true" transports="https http" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<enrich>
<source clone="true" type="body"/>
<target property="storeBody" type="property"/>
</enrich>
<payloadFactory media-type="xml">
<format>
<Root xmlns="">
<Child/>
</Root>
</format>
<args/>
</payloadFactory>
<iterate expression="//Root/Child">
<target>
<sequence>
<enrich>
<source clone="true" property="storeBody" type="property"/>
<target type="body"/>
</enrich>
<send>
<endpoint key="WSRTE_reg"/>
</send>
</sequence>
</target>
</iterate>
</inSequence>
<outSequence/>
<faultSequence>
<payloadFactory media-type="xml">
<format>
<Error xmlns="">Error</Error>
</format>
<args/>
</payloadFactory>
<header action="remove" name="wsse:Security" scope="default" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-
secext-1.0.xsd"/>
<respond/>
</faultSequence>
</target>
<policy key="gov:ihp360/AA/AA_security_policy.xml"/>
<enableSec/>
</proxy>
To make matters worse, once the error has occurred once, the ESB throws the same error even when the backend does not time out and needs to be restarted before it works again.
Any suggestions?
Related
I am converting a csv file, where each csv record is getting converted to json. I am using an iterator mediator to send each json object to an endpoint by modifying it using payload-factory mediator. But I get this VFS error at the end. How can I fix this?
ERROR {VFSTransportSender} - Error while attaching VFS file system properties. null
[2022-07-20 19:30:46,925] ERROR {VFSTransportSender} - Unable to determine out transport information to send message
[2022-07-20 19:30:46,929] ERROR {Axis2Sender} - {proxy:TestProxy} Access-Control-Allow-Credentials:true,Access-Control-Allow-Headers:Authorization, Content-Type, fluent.account,Access-Control-Allow-Methods:POST, PUT, GET, OPTIONS, DELETE,Access-Control-Allow-Origin:*,Access-Control-Expose-Headers:flex.type, flex.version,Access-Control-Max-Age:3600,Cache-Control:no-cache, no-store, max-age=0, must-revalidate,Connection:keep-alive,Content-Type:application/json;charset=UTF-8,Date:Wed, 20 Jul 2022 14:00:47 GMT,Expires:0,Pragma:no-cache,Server:nginx/1.10.3 (Ubuntu),Transfer-Encoding:chunked,X-Content-Type-Options:nosniff,X-Frame-Options:DENY,X-XSS-Protection:1; mode=block, Unexpected error sending message back org.apache.axis2.AxisFault: Unable to determine out transport information to send message
at org.apache.axis2.transport.base.AbstractTransportSender.handleException(AbstractTransportSender.java:234)
at org.apache.synapse.transport.vfs.VFSTransportSender.writeFile(VFSTransportSender.java:331)
at org.apache.synapse.transport.vfs.VFSTransportSender.sendMessage(VFSTransportSender.java:189)
at org.apache.axis2.transport.base.AbstractTransportSender.invoke(AbstractTransportSender.java:119)
at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:442)
at org.apache.synapse.core.axis2.Axis2Sender.sendBack(Axis2Sender.java:213)
at org.apache.synapse.mediators.builtin.RespondMediator.mediate(RespondMediator.java:46)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:109)
at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:263)
at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.mediateFromContinuationStateStack(Axis2SynapseEnvironment.java:820)
at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:322)
at org.apache.synapse.core.axis2.SynapseCallbackReceiver.handleMessage(SynapseCallbackReceiver.java:608)
at org.apache.synapse.core.axis2.SynapseCallbackReceiver.receive(SynapseCallbackReceiver.java:207)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
at org.apache.synapse.transport.passthru.ClientWorker.run(ClientWorker.java:298)
at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Synapse Configs
<?xml version="1.0" encoding="UTF-8"?>
<proxy name="TestProxy" startOnLoad="true" transports="http https vfs" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<smooks config-key="smooks_conf">
<input type="text"/>
<output type="xml"/>
</smooks>
<log level="full"/>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<log>
<property expression="json-eval($)" name="Response"/>
</log>
<call-template target="Template"/>
<log>
<property name="Info" value="Before Iteration"/>
</log>
<iterate continueParent="true" expression="$body//ProductData/Product" id="Iterate-over-products" xmlns:ns="http://org.apache.synapse/xsd">
<target>
<sequence>
<log>
<property name="Info" value="Inside Iteration"/>
</log>
<payloadFactory media-type="json">
<format>
{
"ref": "$1",
"name": "$2",
"summary": "This is a HP",
"attributes": [
{
"name": "imageUrl",
"type": "STRING",
"value": "$3"
},
]
}
}
</format>
<args>
<arg evaluator="json" expression="$.Product.ProductCode" />
<arg evaluator="json" expression="$.Product.ProductName" />
<arg evaluator="json" expression="$.Product.ProductUrl"/>
</args>
</payloadFactory>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<call>
<endpoint>
<http method="post" uri-template""=>
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>-1</progressionFactor>
<maximumDuration>0</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
<log>
<property expression="json-eval($)" name="product"/>
</log>
</sequence>
</target>
</iterate>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</target>
<parameter name="transport.vfs.Streaming">true</parameter>
<parameter name="transport.PollInterval">1</parameter>
<parameter name="transport.vfs.FileURI">file://C://in</parameter>
<parameter name="transport.vfs.ContentType">text/plain</parameter>
<parameter name="transport.vfs.ActionAfterProcess">MOVE</parameter>
<parameter name="transport.vfs.MoveAfterFailure">file://C:/out</parameter>
<parameter name="transport.vfs.ActionAfterFailure">MOVE</parameter>
<parameter name="transport.vfs.FileNamePattern">.*.csv</parameter>
<parameter name="transport.vfs.MoveAfterProcess">file://C:/history</parameter>
</proxy>
All the logs just before the iterate mediator get printed. The flow stops from the iterate mediator and produce the VFS transport error
Since you are using a custom connector within the template I'm assuming your connector is not properly written which overrides the current message context. Hence after the connector, there is no content to Iterate over. In order to get around this issue save the message to a property after the Smooks mediator and then restore the message before the Iterate mediator. For this, You can use the Enrich Mediator.
To Save the payload
<enrich>
<source type="body"/>
<target type="property" property="jsonPayload"/>
</enrich>
To restore the payload
<enrich description="Restore original payload">
<source clone="false" property="jsonPayload" type="property"/>
<target type="body"/>
</enrich>
Additional notes: When you are using Iterate Mediator It should be always accompanied by an Aggregate mediator. You can read more about this here.
I have a REST service that returns a json simple {message: "ok"}. When I use Respond Mediator this stop further processing of a message and send the message back to the client.
I need to send response to client, and then execute task asynchronously, but if I use it ignores the next call to a sequence or an endpoint.
How can you respond synchronously (response to client) and then invoke a service, without response mediator ignore the next mediator?
thanks;
I was able to solve the challenge. effectively Clone mediator not just clone message, it give new separate life to new message.
<api xmlns="http://ws.apache.org/ns/synapse" name="porticApiAsyn" context="/test">
<resource methods="POST" url-mapping="/asyn">
<inSequence>
<log>
<property name="message" value="asyn"/>
</log>
<payloadFactory media-type="json">
<format>{"message":"asyn test"}</format>
<args/>
</payloadFactory>
<clone continueParent="true" sequential="true">
<target sequence="logSequence"/>
</clone>
<respond/>
</inSequence>
In this case, the message is sent to logsequence, then the response mediator is executed. Thanks for your help.
For your case you could even do the following
<api xmlns="http://ws.apache.org/ns/synapse" name="porticApiAsyn" context="/test">
<resource methods="POST" url-mapping="/asyn">
<inSequence>
<log>
<property name="message" value="asyn"/>
</log>
<payloadFactory media-type="json">
<format>{"message":"asyn test"}</format>
<args/>
</payloadFactory>
<clone continueParent="true" sequential="true">
<target sequence="logSequence"/>
<target>
<sequence>
<respond/>
</sequence>
</target>
</clone>
</inSequence>
I guess it should work as well and is maybe more readable
I am using WSO2 ESB with RabbitMQ, I have two proxy services:
AMQPProducerSample, it receives messages via HTTP transport and send it to RabbitMQ queue
AMQPProxy it works as consumer for RabbitMQ queue (via rabbitmq transport), consumed messages are send to HTTP endpoint SampleEndPoint
Everything works fine except one scenario:
My backend service set in SampleEndPoint goes down.
New messages arrives and are published via AMQPProducerSample, delivery fails (that is expected because my backend is down). In console I can see:
WARN - ConnectCallback Connection refused or failed for : mfb.localhost/127.0.0.1:80
WARN - FaultHandler ERROR_CODE : 101503
WARN - FaultHandler ERROR_MESSAGE : Error connecting to the back end
WARN - FaultHandler ERROR_DETAIL : Error connecting to the back end
WARN - FaultHandler ERROR_EXCEPTION : null
WARN - FaultHandler FaultHandler : Endpoint [SampleEndPoint]
My backend service recovers and is available
New messages arrives and are published via AMQPProducerSample but my endpoint does not receive any message any more. It works fine only if number of undelivered messages is below 5. In that case messages are successfully delivered to backend service. The delivery always stops working after 5 (five) undelivered messages.
How to solve this? Is there any option I need to set or change to make it work all the time?
I am using WSO2 ESB 4.8.1
Below is my full config:
<?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 name="AMQPProxy"
transports="rabbitmq"
startOnLoad="true"
trace="enable">
<description/>
<target>
<inSequence>
<log level="full"/>
<property name="OUT_ONLY" value="true"/>
<property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
<send>
<endpoint key="SampleEndPoint"/>
</send>
</inSequence>
</target>
<parameter name="rabbitmq.queue.name">queue</parameter>
<parameter name="rabbitmq.connection.factory">AMQPConnectionFactory</parameter>
<parameter name="rabbitmq.exchange.name">exchange</parameter>
<parameter name="rabbitmq.queue.routing.key">route</parameter>
</proxy>
<proxy name="AMQPProducerSample"
transports="http"
startOnLoad="true"
trace="disable">
<description/>
<target>
<inSequence>
<property name="OUT_ONLY" value="true"/>
<property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
<property name="NO_KEEPALIVE" value="true" scope="axis2"/>
<send>
<endpoint>
<address uri="rabbitmq:/AMQPProxy?rabbitmq.server.host.name=localhost&rabbitmq.server.port=5672&rabbitmq.queue.name=queue&rabbitmq.queue.routing.key=route&rabbitmq.exchange.name=exchange"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<send/>
</outSequence>
</target>
</proxy>
<endpoint name="SampleEndPoint">
<address uri="http://mfb.localhost/">
<timeout>
<duration>1000</duration>
<responseAction>discard</responseAction>
</timeout>
<suspendOnFailure>
<errorCodes>-1</errorCodes>
<progressionFactor>1.0</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<errorCodes>-1</errorCodes>
</markForSuspension>
</address>
</endpoint>
<sequence name="fault">
<log level="full">
<property name="MESSAGE" value="Executing default 'fault' sequence"/>
<property name="ERROR_CODE" expression="get-property('ERROR_CODE')"/>
<property name="ERROR_MESSAGE" expression="get-property('ERROR_MESSAGE')"/>
</log>
<drop/>
</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>
</definitions>
This is a known bug which was there in ESB 4.8.1 fresh pack. Later on we have fixed it. So I recommend you to switch into ESB 4.9.0 release where this issue was fixed.
[1] https://docs.wso2.com/display/ESB490/Downloading+the+Product
You have to change the following parameter within transportReceiver for rabbitmq in axis2.xml
<parameter name="rabbitmq.connection.retry.count" locked="false">5</parameter>
"rabbitmq.connection.retry.count" is the number of times attempted to reconnect after each retry, I think you have set it to 5, that is why connection drop after five attempts. Increse the parameter value and try it.
I have a simple proxy in WSO2 ESB, and sometimes backend service
process request for a long time and I catch a timeout on the ESB. I dont want to increase timeout, I just want to handle this error in sequence and send error message back.
But when endpoint is timed out I cant send payloaded message back
ESB log:
ERROR - ClientUtils The system cannot infer the transport information from the /services/restEventReaderSoap URL.
ERROR - Axis2Sender Unexpected error during sending message out org.apache.axis2.AxisFault: The system cannot infer the transport information from the /services/restEventReaderSoap URL.
at org.apache.axis2.description.ClientUtils.inferOutTransport(ClientUtils.java:81)
at org.apache.synapse.core.axis2.DynamicAxisOperation$DynamicOperationClient.executeImpl(DynamicAxisOperation.java:115)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:149)
at org.apache.synapse.core.axis2.Axis2FlexibleMEPClient.send(Axis2FlexibleMEPClient.java:482)`
Proxy config:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="restEventReaderSoap"
transports="https http"
startOnLoad="true"
trace="disable">
<description/>
<target>
<inSequence>
<send>
<endpoint>
<address uri="http://myserver/RestInformation" format="soap11">
<timeout>
<duration>1000</duration>
<responseAction>fault</responseAction>
</timeout>
</address>
</endpoint>
</send>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence>
<payloadFactory media-type="xml">
<format>
<Send>
<id>$1</id>
</Send>
</format>
<args>
<arg value="Error"/>
</args>
</payloadFactory>
<send/>
</faultSequence>
</target>
</proxy>
Where is my error and what I have to do?
try adding the following in you fault handler :
<header action="remove" name="To" scope="default"/>
<property name="RESPONSE" scope="default" type="STRING" value="true"/>
Check that your service url is correctly pointing towards your wso2 server.
We are using latest version of WSO2 ESB(4.6.0).We are exploring on implementing Proxy Service to a web service. The details are as follows:
An Axis2 Webservice Custom service proxy is setup using WSO2. The configuration is as follows:
Proxy XML: This synapse configuration was generated using WSO2 UI.
<proxy xmlns="http://ws.apache.org/ns/synapse" name="StockQuoteProxy" transports="https,http" statistics="enable" trace="enable" startOnLoad="true">
<target faultSequence="myFaultHandler">
<inSequence>
<property name="DISABLE_CHUNKING" value="true" scope="axis2" type="STRING"/>
</inSequence>
<outSequence>
<send/>
</outSequence>
<endpoint>
<address uri="http://localhost:9000/services/SimpleStockQuoteService">
<timeout>
<duration>3000</duration>
<responseAction>fault</responseAction>
</timeout>
<suspendOnFailure>
<errorCodes>101504,101505</errorCodes>
<initialDuration>1000</initialDuration>
<progressionFactor>2.0</progressionFactor>
<maximumDuration>10000</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<errorCodes>101507,101508,101505,101506,101509,101500,101510,101001,101000,101503,101504,101501</errorCodes>
<retriesBeforeSuspension>1</retriesBeforeSuspension>
<retryDelay>1</retryDelay>
</markForSuspension>
</address>
</endpoint>
</target>
<publishWSDL uri="http:// localhost:9000/services/SimpleStockQuoteService?wsdl"/>
<description></description>
</proxy>
Sequence myFaultHandler XML:
<sequence xmlns="http://ws.apache.org/ns/synapse" name="myFaultHandler" trace="enable">
<header name="To" action="remove"/>
<property name="RESPONSE" value="true"/>
<property name="NO_ENTITY_BODY" action="remove" scope="axis2"/>
<log level="custom">
<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')"/>
</log>
<makefault version="soap12">
<code xmlns:soap12Env="http://www.w3.org/2003/05/soap-envelope" value="soap12Env:Receiver"/>
<reason value="Webservice is either down or currently not reachable."/>
<node></node>
<role></role>
</makefault>
<send/>
</sequence>
When the webservice is down, this configuration throws a soap fault as defined.
When the webservice is taking time to send the response back, as defined in the proxy XML configuration it should timeout after 3 sec:
<timeout>
<duration>3000</duration>
<responseAction>fault</responseAction>
</timeout>
Even after the timeout period the proxy is still waiting for the response instead of throwing the fault back.
On analysis of the log file, we tried by modifying the following parameters in the below mentioned properties file but still the thread was stuck waiting for the response.
**synapse.properties**
synapse.global_timeout_interval=3000
synapse.connection.read_timeout=3000
synapse.connection.connect_timeout=3000
synapse.timeout_handler_interval=3000
**nhttp.properties**
http.socket.timeout=5000
It eventually times out and throws socket exception.
As per the specification (http://wso2.com/library/articles/wso2-enterprise-service-bus-endpoint-error-handling) after the timeout happens the endpoint should go to Timeout state, but in this case the endpoint is still in Active state and it is neither faulting nor discarding message. Some times it throws an error code 504. But this action is not consistent.
Please let know the changes required for a given proxy service to timeout/discard message, if the final webservice is very slow.
If you are using http transport from the axis2.xml (which locates at CARBON_HOME/repository/conf/axis2 directory), you can fix that by configuring the time out parameters in that particular transport sender by adding parameters. For example,
<parameter name="SO_TIMEOUT">3000</parameter>
<parameter name="CONNECTION_TIMEOUT">3000</parameter>
Regards,
Asanka Sanjeewa.