mule 3.5 follow redirects on outbound endpoint - http

I have the simple flows as following. When we hit one flow, it hits another flow and gets http.status 302 and Location , which means it must redirect to the location in Location header. But it is throwing exception.
<flow name="httpconnectorFlowRedirection">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="9876" path="redirect" connector-ref="NoSessionEncodingConnector" doc:name="HTTP"/>
<http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="9876" method="POST" doc:name="HTTP" path="temp" connector-ref="NoSessionEncodingConnector" contentType="text/plain"
followRedirects="true" />
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>
<flow name="temp_flow">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="9876" path="temp" connector-ref="NoSessionEncodingConnector" doc:name="HTTP" />
<logger message="in temp flow" level="INFO" doc:name="Logger"/>
<set-property propertyName="http.status" value="307" doc:name="Property" />
<set-property propertyName="Location" value="http://localhost:9876/samplehttp" doc:name="Property" />
</flow>
Error I am getting is as follows
org.mule.exception.DefaultMessagingExceptionStrategy:
********************************************************************************
Message : Failed to route event via endpoint: DefaultOutboundEndpoint{endpointUri=http://localhost:9876/temp, connector=HttpConnector
{
name=NoSessionEncodingConnector
lifecycle=start
this=14c5f0c
numberOfConcurrentTransactedReceivers=4
createMultipleTransactedReceivers=true
connected=true
supportedProtocols=[http]
serviceOverrides=
session.handler=org.mule.session.NullSessionHandler
}
, name='endpoint.http.localhost.9876.temp', mep=REQUEST_RESPONSE, properties={exceptionOnMessageError=true, http.method=POST, followRedirects=true, Content-Type=text/plain}, transactionConfig=Transaction{factory=null, action=INDIFFERENT, timeout=0}, deleteUnacceptedMessages=false, initialState=started, responseTimeout=10000, endpointEncoding=UTF-8, disableTransportTransformer=false}. Message payload is of type: PostMethod
Type : org.mule.api.transport.DispatchException
Code : MULE_ERROR--2
JavaDoc : http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/transport/Dispat chException.html
Payload : org.apache.commons.httpclient.methods.PostMethod#14efe2e
********************************************************************************
I am getting this error only when follow redirects set to true on outbound endpoint
I am using mule 3.5.

I got the answer. I need to use GET reqeust for successful redirection.
But if I use http listeners(since mule 3.6), I am able to redirect even for POST requests. Consider the following example.
<http:listener-config name="GlobalHTTPConnector" host="localhost" port="9876" doc:name="HTTP Listener Configuration" basePath="mulelearning"/>
<flow name="redirection-flow">
<http:listener config-ref="GlobalHTTPConnector" path="/requestredir" doc:name="HTTP"/>
<!--
When followRedirects is set to true, when http.status from called service is redirection(eg:301), it redirects to new location.
In this case /redFlow1 sends a redirection code 301 and location header. Hence it redirects to /redFlow2 (see the flows below) and gives us the response 'payload from red-flow2'
-->
<http:request config-ref="HTTP_Request_Configuration" path="/redFlow1" method="POST" followRedirects="true" doc:name="HTTP" />
</flow>
<flow name="red-ser1">
<http:listener config-ref="GlobalHTTPConnector" path="/redFlow1" doc:name="HTTP"/>
<logger level="INFO" doc:name="Logger" message="I am in red-flow1"/>
<set-payload value="payload from red-flow1" />
<set-property propertyName="http.status" value="301" doc:name="Property" />
<set-property propertyName="Location" value="http://localhost:9876/mulelearning/redFlow2" doc:name="Property" />
</flow>
<flow name="red-ser2">
<http:listener config-ref="GlobalHTTPConnector" path="/redFlow2" doc:name="HTTP"/>
<set-payload value="payload from red-flow2" />
<logger level="INFO" doc:name="Logger" message="I am in red-flow2"/>
</flow>

Related

Mule CE 3.6.1 HTTP Request url encoding issue

I have a Mule flow which uses HTTP Request endpoint in Mule CE3.6.1. It needs to use encoded HTTP url to get the correct data.
Please note the encoded url: /items?q=%2Blabel%3ABOTV2309H*%20%2Bparent.uri%3A%5C%2Fbristol%5C%2Ftest%5C%2Fgateway%5C%2F*&rows=100&start=0
Here is the test flow.
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" version="CE-3.6.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd">
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8089" basePath="/" usePersistentConnections="false" doc:name="HTTP Listener Configuration"/>
<http:request-config name="HTTP_Request_Config_Search" host="testserver" port="80" basePath="/index" usePersistentConnections="false" doc:name="HTTP Request Configuration"/>
<flow name="testFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="*" allowedMethods="POST" doc:name="HTTP"/>
<object-to-string-transformer doc:name="Object to String"/>
<logger level="INFO" doc:name="Logger"/>
<http:request config-ref="HTTP_Request_Config_Search" path="/items?q=%2Blabel%3ABOTV2309H*%20%2Bparent.uri%3A%5C%2Fbristol%5C%2Ftest%5C%2Fgateway%5C%2F*&rows=100&start=0" method="GET" doc:name="HTTP"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>
</mule>
When the Mule flow runs, here is the url being requested (Found through wireshark):
/items?q=%20label%3ABOTV2309H%2A%20%20parent.uri%3A%5C%2Fbristol%5C%2Ftest%5C%2Fgateway%5C%2F%2A&rows=100&start=0
Please note %2B is replaced with %20 in two places, which obviously do not return the data I need.
Is this an issue with HTTP endpoint?
Thanks!
I divided the params into query and uri params. Then this issue got resolved.
<http:request config-ref="HTTP_Request_Config_Search" path="/items" method="GET" doc:name="HTTP">
<http:request-builder>
<http:query-param paramName="q" value="+label:BOTV2309H* +parent.uri:\/test\/gateway\/*"/>
<http:uri-param paramName="rows" value="100"/>
<http:uri-param paramName="start" value="0"/>
</http:request-builder>
</http:request>

How to pass hash map object to http outbound in mule?

I need to pass hash map object to Http outbound using post method in mule.
How can it be done?
Hope this can help
<flow name="demoFlow1" doc:name="demoFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="hi" doc:name="HTTP"/>
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy">
<scripting:text><![CDATA[
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "Eddu");
map.put("lastname", "Melendez");
return map;
]]></scripting:text>
</scripting:script>
</scripting:component>
<http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="print" method="POST" doc:name="HTTP"/>
</flow>
<flow name="demoFlow2" doc:name="demoFlow2">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="print" doc:name="HTTP"/>
<logger level="INFO" message="#[message.payloadAs(java.lang.String)]" doc:name="Logger"/>
</flow>
This will be the output if you send a map through the service:
INFO 2015-01-22 08:30:42,298 [[demo].connector.http.mule.default.receiver.03] org.mule.api.processor.LoggerMessageProcessor: name=Eddu&lastname=Melendez
You can also add the line below, in order to get a json instead query params in http
As you can see the response will be different
INFO 2015-01-22 08:32:31,014 [[demo].connector.http.mule.default.receiver.03] org.mule.api.processor.LoggerMessageProcessor: {"name":"Eddu","lastname":"Melendez"}

Mule ESB HTTP POST Request with URL-Form-Encoded Body

I'm new in Mule ESB and trying to send a post request to a REST Service. The body of the request is in String form and the request should be x-www-form-urlencoded. I set the payload to my parameters and send the request to the REST Service but I get an exception:
Failed to invoke REST service "http://username:password#192.168.10.252/api/rest/session/login.json". Message payload is of type: String
My Rest URL is: (#[restURL]) ${dms.host}/api/rest/session/login.json
My parameter is (set as payload #[restBody]): username=user&password=pass
<sub-flow name="RESTrequestToDMS" doc:name="RESTrequestToDMS" processingStrategy="synchronous">
<set-variable variableName="originalMessage" value="#[payload]" doc:name="Backup original message"/>
<logger message="#[restBody]" level="INFO" doc:name="Logger"/>
<choice doc:name="Choice">
<when expression="restHTTPmethod == 'POST'">
<processor-chain>
<set-payload value="#[restBody]" doc:name="Set Payload"/>
<http:rest-service-component httpMethod="POST" serviceUrl="http://${dms.user}:${dms.pass}##[restURL]"></http:rest-service-component>
</processor-chain>
</when>
<when expression="restHTTPmethod == 'GET'">
<processor-chain>
<http:rest-service-component httpMethod="GET" serviceUrl="http://${dms.user}:${dms.pass}##[restURL]?#[restBody]"></http:rest-service-component>
</processor-chain>
</when>
<otherwise>
<processor-chain>
<logger message="Unknown http method type is provided! " level="ERROR" doc:name="Logger"/>
</processor-chain>
</otherwise>
</choice>
<json:json-to-object-transformer returnClass="java.util.Map" doc:name="JSON to Object"/>
<echo-component doc:name="Echo"/>
<set-variable variableName="RESTResponse" value="#[payload]" doc:name="set RESTResponse"/>
<set-payload value="#[flowVars['originalMessage']]" doc:name="Restore Original Message"/>
</sub-flow>
Can somebody help me figure this out please?
Thanks a lot in advance.
Note: Updated according to David's reply.
-------------------UPDATE--------------------
So now, for testing purposes, I have modified the flow like this:
<set-payload value="#[restBody]" doc:name="Set Payload"/>
<custom-transformer class="de.mfg.osii.http.StringToURIParametersMapTransformer" doc:name="String To URI Parameters"/>
<http:rest-service-component httpMethod="POST" serviceUrl="http://${dms.user}:${dms.pass}##[restURL]">
<http:requiredParameter key="username" value="#[payload.get('username')]" />
<http:requiredParameter key="password" value="#[payload.get('password')]" />
</http:rest-service-component>
So now the payload is: {username=user, password=pass}
But now when I try to run this, I get the following error:
1. Failed to invoke REST service "http://user:pass#192.168.10.252/api/rest/session/login.json". Message payload is of type: LinkedHashMap (org.mule.transport.http.components.RestServiceException)
Update: The above problem, the exception, has just been solved by adding a message-property "Content-Type" with the value "application/x-www-form-urlencoded".
Still the last part, below, remains a mystery for me :)
The other thing is, as I stated in the comment to David's answer, can I add the required parameters for the rest component in an adaptive way? To be more clearer, I do not want to create different flows for every different request. I have the parameter map in the payload, so I want to iterate over them and put them in the required parameters. Is something like this possible?
Thanks a lot in advance!
-------------------UPDATE--------------------
So, I've modified my flow and used David's suggestions. However, now, I'm getting an HTTP 405 error (Method not allowed). But I'm sure I'm posting to the correct address with correct content-type. What is the reason for this? Does anybody have an idea?
My payload coming into this flow is a string (url encoded parameters) such as ->
sessionId=9eub9gm7k7oc1ub81dhef6t46q&xml=%3CObjectList%3E%3CFolderObject%3E%3CAddToFolder%20RefType%3D%22Path%22%20ClassName%3D%22FolderObject%22%3E%3C!%5BCDATA%5B%2FfolderPath%5D%5D%3E%3C%2FAddToFolder%3E%3CName%3E%3C!%5BCDATA%5Baaa%5D%5D%3E%3C%2FName%3E%3CDescription%3E%3C!%5BCDATA%5BRequests%20from%20user%20aaa%20are%20stored%20in%20this%20folder%5D%5D%3E%3C%2FDescription%3E%3CNoErrorIfExist%2F%3E%3C%2FFolderObject%3E%3C%2FObjectList%3E
<flow name="RESTrequestToDMS" doc:name="RESTrequestToDMS" processingStrategy="synchronous">
<set-variable variableName="originalMessage" value="#[payload]" doc:name="Backup original message"/>
<choice doc:name="Choice">
<when expression="restHTTPmethod == 'POST'">
<processor-chain>
<set-payload value="#[restBody]" doc:name="Set Payload"/>
<logger message="The payload before http post is: #[message.payload]" level="INFO" doc:name="Logger"/>
<http:outbound-endpoint exchange-pattern="request-response" doc:name="HTTP" address="http://#[restURL]" user="${dms.user}" password="${dms.pass}" contentType="application/x-www-form-urlencoded">
</http:outbound-endpoint>
</processor-chain>
</when>
<when expression="restHTTPmethod == 'GET'">
<processor-chain>
<http:outbound-endpoint method="GET" exchange-pattern="request-response" doc:name="HTTP" address="http://#[restURL]?#[restBody]" user="${dms.user}" password="${dms.pass}" contentType="application/x-www-form-urlencoded">
</http:outbound-endpoint>
</processor-chain>
</when>
<otherwise>
<processor-chain>
<logger message="Unknown http method type is provided! " level="ERROR" doc:name="Logger"/>
</processor-chain>
</otherwise>
</choice>
<echo-component doc:name="Echo"/>
<choice doc:name="Choice">
<when expression="payload != null && payload != empty && payload != ''">
<processor-chain>
<json:json-to-object-transformer doc:name="JSON to Object" returnClass="java.util.Map"/>
<set-variable variableName="RESTResponse" value="#[payload]" doc:name="set RESTResponse"/>
</processor-chain>
</when>
<otherwise>
<processor-chain>
<logger message="The payload is null or empty! HTTP response code is: #[message.inboundProperties['http.status']]" level="INFO" doc:name="Logger"/>
<set-variable variableName="RESTResponse" value="#[message.inboundProperties['http.status']]" doc:name="Set HTTP Status Code"/>
</processor-chain>
</otherwise>
</choice>
<set-payload value="#[flowVars['originalMessage']]" doc:name="Restore Original Message"/>
</flow>
Here is how you pass parameters to be URL encoded with the rest-service-component:
<http:rest-service-component httpMethod="POST"
serviceUrl="http://${dms.user}:${dms.pass}##[restURL]">
<http:requiredParameter key="username" value="user" />
<http:requiredParameter key="password" value="pass" />
</http:rest-service-component>

Mule - test an http get request with choice component

I have the following flow :
<flow name="SOAPWebService" doc:name="SOAPWebService">
<http:inbound-endpoint address="http://localhost:8088/esb/" exchange-pattern="request-response" doc:name="HTTP">
</http:inbound-endpoint>
<choice doc:name="Choice">
<when expression="#[payload.contains('c22')]">
<set-variable variableName="paramCtr" value="#[message.inboundProperties['ctr']]" doc:name="conteneur"/>
<set-variable variableName="paramC" value="#[message.inboundProperties['c']]" doc:name="critere"/>
<component class="com.example.components.SampleComponent" doc:name="Java"/>
<mulexml:xslt-transformer maxIdleTransformers="2" maxActiveTransformers="5" xsl-file="C:\MuleStudio\SandBox\resources\PrepareRequestXMLPort.xsl" doc:name="XSLT">
<mulexml:context-property key="paramCtr" value="#[flowVars['paramCtr']]"/>
<mulexml:context-property key="paramC" value="#[flowVars['paramC']]"/>
</mulexml:xslt-transformer>
<cxf:proxy-client payload="body" enableMuleSoapHeaders="true" doc:name="SOAP"/>
<http:outbound-endpoint exchange-pattern="request-response" address="http://localhost:8080/ClientsDB/port" doc:name="PortWS"/>
</when>
<otherwise>
<set-variable variableName="paramCtr" value="#[message.inboundProperties['ctr']]" doc:name="conteneur"/>
<set-variable variableName="paramC" value="#[message.inboundProperties['c']]" doc:name="critere"/>
<component class="com.example.components.SampleComponent" doc:name="Java"/>
<mulexml:xslt-transformer maxIdleTransformers="2" maxActiveTransformers="5" xsl-file="C:\MuleStudio\SandBox\resources\PrepareRequestXMLDouane.xsl" doc:name="XSLT">
<mulexml:context-property key="paramCtr" value="#[flowVars['paramCtr']]"/>
<mulexml:context-property key="paramC" value="#[flowVars['paramC']]"/>
</mulexml:xslt-transformer>
<cxf:proxy-client payload="body" enableMuleSoapHeaders="true" doc:name="SOAP"/>
<http:outbound-endpoint exchange-pattern="request-response" address="http://localhost:8080/ClientsDB/douane" doc:name="DouaneWS"/>
</otherwise>
</choice>
<byte-array-to-string-transformer doc:name="Byte Array to String" />
<file:outbound-endpoint path="C:\MuleStudio\SandBox\output" outputPattern="#[function:datestamp:dd-MM-yy]_#[function:systime].xml " responseTimeout="10000" doc:name="Outgoing File"/>
I want to test if an http request like http://localhost:8088/esb/?type=xxxx&id=1234 if it contains the String xxxx in a way to route the request to the desired web service proxy.
I've tried withe the expression expression="#[string.contains['xxxxx']]" but it does not seem to work.
any idea?
thank you.
Two things: You will need to replace "string" with the property you want to execute on. Either a message property or payload etc. i.e #[payload.contains...].
"contains" is a Java method on java.lang.String so you need to use standard Java method invocation with () instead of [].
Working example:
<choice doc:name="Choice">
<when expression="#[payload.contains('xxxx')]">
<logger level="ERROR" message="YES" />
</when>
<otherwise>
<logger level="ERROR" message="NO" />
</otherwise>
</choice>
Or directly work off inbound properties for your query params:
After your http inbound use set-variable to store your query params into flow variables.
And then use the flow variales in your expression.
<set-variable value="#[message.inboundProperties['id']]" variableName="paramId"></set-variable>
<set-variable value="#[message.inboundProperties['type']]" variableName="paramType"></set-variable>
or you can directly use inbound property for comparision.
<when expression="#[message.inboundProperties['type']== 'XXXX']">

Mule - choice component issue

When I run my flow, I get the following error `
<org.apache.cxf.staxutils.DepthXMLStreamReader>
<reader class="org.mule.module.cxf.support.StreamClosingInterceptor$1">
<reader class="com.ctc.wstx.sr.ValidatingStreamReader">
<mXml11>false</mXml11>
<mInputBuffer>xmlns:ns2="http://wsdouane/"><return><douanePK><idConteneurId>ctr1</idConteneurId><idCritereId>C11</idCritereId></douanePK><valeurId>oui</valeurId></return></ns2:findResponse></S:Body></S:Envelope>.................
we can see the correct soap response starting from the <mInputBuffer>, is there a way to get only the soap response??
here is my flow
<flow name="SOAPWebService" doc:name="SOAPWebService">
<http:inbound-endpoint exchange-pattern="request-response" address="http://localhost:8088/esb" doc:name="HTTP"/>
<object-to-string-transformer doc:name="Object to String"/>
<choice doc:name="Choice">
<when expression="#[payload.contains('C22')]">
<set-variable variableName="paramCtr" value="#[message.inboundProperties['ctr']]" doc:name="conteneur"/>
<set-variable variableName="paramC" value="#[message.inboundProperties['c']]" doc:name="critere"/>
<component class="com.example.components.SampleComponent" doc:name="Java"/>
<mulexml:xslt-transformer maxIdleTransformers="2" maxActiveTransformers="5" xsl-file="C:\MuleStudio\SandBox\resources\PrepareRequestXMLPort.xsl" doc:name="XSLT">
<mulexml:context-property key="paramCtr" value="#[flowVars['paramCtr']]" />
<mulexml:context-property key="paramC" value="#[flowVars['paramC']]" />
</mulexml:xslt-transformer>
<cxf:proxy-client payload="body" enableMuleSoapHeaders="true" doc:name="SOAP"/>
<http:outbound-endpoint exchange-pattern="request-response" address="http://localhost:8080/ClientsDB/port" doc:name="PortWS"/>
<byte-array-to-string-transformer doc:name="Byte Array to String" />
</when>
<otherwise>
<set-variable variableName="paramCtr" value="#[message.inboundProperties['ctr']]" doc:name="conteneur"/>
<set-variable variableName="paramC" value="#[message.inboundProperties['c']]" doc:name="critere"/>
<component class="com.example.components.SampleComponent" doc:name="Java"/>
<mulexml:xslt-transformer maxIdleTransformers="2" maxActiveTransformers="5" xsl-file="C:\MuleStudio\SandBox\resources\PrepareRequestXMLDouane.xsl" doc:name="XSLT">
<mulexml:context-property key="paramCtr" value="#[flowVars['paramCtr']]" />
<mulexml:context-property key="paramC" value="#[flowVars['paramC']]" />
</mulexml:xslt-transformer>
<cxf:proxy-client payload="body" enableMuleSoapHeaders="true" doc:name="SOAP"/>
<http:outbound-endpoint exchange-pattern="request-response" address="http://localhost:8080/ClientsDB/douane" doc:name="DouaneWS"/>
<byte-array-to-string-transformer doc:name="Byte Array to String"/>
</otherwise>
</choice>
<xm:object-to-xml-transformer doc:name="Object to XML"/>
<file:outbound-endpoint path="C:\MuleStudio\SandBox\output" outputPattern="#[function:datestamp:dd-MM-yy]_#[function:systime].xml " responseTimeout="10000" doc:name="Outgoing File"/>
</flow>
thank you.
This expression #[payload.contains('c22')] can't work because the payload is an InputStream. Aren't you seeing stack traces in Mule's logs?
In any case, try adding <object-to-string-transformer /> before the choice and see if it fixes the issue.
EDIT:
The problem is that you're using XStream (in xm:object-to-xml-transformer) to serialize the CXF response object (org.apache.cxf.staxutils.DepthXMLStreamReader) into XML. The CXF response should not be messed with and should be handled by the cxf:proxy-client in the response phase of the flow. The xm:object-to-xml-transformer and file:outbound-endpoint after the choice router are probably disturbing this mechanism. Try to wrap them in a response element above the choice router to they execute after it in the response phase.
Note that I have already given you this advice in your other question https://stackoverflow.com/a/16615537/387927 but you did not react to it.
Also I don't think byte-array-to-string-transformer does anything: the message payload after the http:outbound-endpoints should be org.apache.cxf.staxutils.DepthXMLStreamReader, preventing this transformer to fire.

Resources