How to Edit Default Mule Error message..? - http

I have defined a Mule HTTP Inbound Endpoint as :
<flow name="jfeed_fill_data">
<http:inbound-endpoint address="http://localhost:1212/jcore/insert/feed/">
</http:inbound-endpoint>
<component class="main.java.com.joshlabs.jcore.Feed"/>
</flow>
Now this Service Works Fine.
But When i type a Deformed URL , something like "http://localhost:1212/jcore/insert/feedasdasdAwes/", I get the following Message from MULE :
Cannot bind to address "http://localhost:1212/jcore/insert/feedasdasdAwes/"
No component registered on that endpoint
My Question is : How can i Change the above default Message to Something of my own.?
Note : Actually i wanted to return a JSON String as an Error message. Something like :
{
Exception: "Invalid URL"
}
And if possible, then "Can MULE throw HTTP 404 : Not Found Error in above case"..??

You just need to make your endpoint accept all sub-paths and then handle wrong ones with message routing:
<flow name="jfeed_fill_data">
<http:inbound-endpoint address="http://localhost:1212" />
<choice>
<when evaluator="header" expression="INBOUND:http.request.path=/jcore/insert/feed/">
<component class="main.java.com.joshlabs.jcore.Feed"/>
</when>
<otherwise>
<message-properties-transformer>
<add-message-property key="http.status" value="404"/>
</message-properties-transformer>
<expression-transformer>
<return-argument evaluator="string" expression="{Exception: "Invalid URL"}"/>
</expression-transformer>
</otherwise>
</choice>
</flow>

Related

How to POST the String Payload to http localhost in mule?

Am new to Mule and I need to POST the string payload which is stored in a variable to http localhost. Below is my configuration.
<flow name="RequestFlow" processingStrategy="synchronous">
<set-variable variableName="variable1" value="#[payload]" doc:name="Set Request"/>
<ws:consumer config-ref="Web_Service_Consumer" doc:name="Web Service Consumer" operation="Submit"/>
<mulexml:dom-to-xml-transformer doc:name="DOM to XML"/>
</flow>
I need to do the POST call before consuming web service.
Please advise.
For instance, you have the following URL-
localhost:8081/getDetails?country=india
and you have a query param named "country". To get this query param in a string format you can use the MEL to store this value in a variable as follows-
[message.inboundProperties.'http.query.params'.country]
Your variable will look like
<set-variable variableName="hello" value="#[message.inboundProperties.'http.query.params'.country]" doc:name="Variable"/>
This would work, just try and reply.
Thanks,
Vibhor
Try the below :-
<set-variable variableName="Variable1" value="#[payload]" doc:name="Variable"/>
<set-payload value="#[flowVars.Variable1]" doc:name="Set Payload"/>
<byte-array-to-string-transformer doc:name="Byte Array to String"/>
<http:request config-ref="HTTP_Request_Configuration" path="test" method="POST" doc:name="HTTP"/>
Hope it helps.

Mule ESB conditional Exchange pattern for UDP/TCP transport

I need to send an acknowledge response for some messages went an acknowledge needed flag is set for that purpose.
Using a Java component I build a Payload string array with this structure:
Payload[0]=message entry.
Payload[1]="true"/"false" // This is the acknowledge needed flag.
Payload[2]="OK"/"ON"/"OFF"// Response to the transport (went flag="true")
This is my XML code
<tcp:connector name="TCP" validateConnections="false" sendBufferSize="0" receiveBufferSize="0" receiveBacklog="0" keepAlive="true" clientSoTimeout="10000" serverSoTimeout="10000" socketSoLinger="0" doc:name="TCP">
<tcp:direct-protocol rethrowExceptionOnRead="true" payloadOnly="true"/>
</tcp:connector>
<flow name="verifyFlow">
<tcp:inbound-endpoint exchange-pattern="request-response" host="localhost" port="9446" connector-ref="TCP" responseTimeout="10000" doc:name="TCP" transformer-refs="Byte_Array_to_String"/>
<component class="verify.as" doc:name="Java Component"/>
<choice doc:name="Choice">
<when expression="#[message.payload[1] == 'false']">
<set-payload value="""" doc:name="No response"/>
</when>
<otherwise>
<expression-transformer mimeType="text/plain" expression="#[message.payload[2]]" doc:name="Expression"/>
</otherwise>
</choice>
</flow>
The problem I'm facing is that went ever the flag is "false" there shouldn't be any response send to the transport (no 'null' value, no empty string, no "", Etc.) ¿Is there any way to change the exchange pattern of the TCP (or UDP) connector from request-response to one way inside the flow?

How to get the incoming cookies to a Mule HTTP end point

I'm using Mule EE 3.5.2.
I'm posting an HTTP request (PostMan) with a cookie header, to an incoming HTTP end point in Mule. How can I read this Cookie?
In practice this cookie will be coming through an NGinX proxy; i need it to pass to another application.
First make sure your connector have enableCookies="true".
Then you'll find a inboundProperty called cookies of type Lorg.apache.commons.httpclient.Cookie.
To access them just #[message.inboundProperties['cookies'].
Here's how to save the cookies from a rest response in a session variable without a custom java class.
<set-session-variable variableName="incomingCookies" value="#[org.mule.transport.http.CookieHelper.parseCookiesAsAClient(message.inboundProperties['set-cookie'],null)]" doc:name="Set incomingCookies as Session Variable"/>
<set-variable variableName="cookie-name" value="#[org.mule.transport.http.CookieHelper.getCookieValueFromCookies(incomingCookieMap,'cookie-name')]" doc:name=“Set cookie-name as Flow Variable”/>
You can use a similar approach for extracting cookies from a rest request using the parseCookiesAsAServer method from the CookieHelper class.
More info on the CookieHelper class is here https://www.mulesoft.org/docs/site/3.8.0/apidocs/org/mule/transport/http/CookieHelper.html
That doesn't work anymore with the new http:listener component.
Setting that property will give :
org.xml.sax.SAXParseException: cvc-complex-type.3.2.2: Attribute 'enableCookies' is not allowed to appear in element 'http:listener'.
So how to do this with the new http:listener component...
A problem I had was that I needed to access the cookies that came in and Mule only provides the cookies in an unformatted string.
So this is an option a friend of mine developed, which I enhanced a bit to get easy access to the cookies in a flow:
package transformers;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.mule.api.MuleMessage;
import org.mule.api.transformer.TransformerException;
import org.mule.api.transport.PropertyScope;
import org.mule.transformer.AbstractMessageTransformer;
import org.mule.transport.http.CookieHelper;
import org.apache.commons.httpclient.Cookie;
public class CookieGrabber extends AbstractMessageTransformer {
public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException {
Object _CookieHeader = message.getInboundProperty("Cookie");
List<Cookie> _CookieList = null;
Map<String,String> _CookieMap = new HashMap<String,String>();
try {
//Grab the cookies from the header and put them into a List
_CookieList = (List<Cookie>) Arrays.asList(CookieHelper.parseCookiesAsAServer(_CookieHeader.toString(),
new URI("" + message.getInboundProperty("host"))));
//And put them in a convenient List which can be accessed from the flow
message.setProperty("incomingCookieList", _CookieList, PropertyScope.SESSION);
//Let's also put them in a nice Map, since incoming cookies will
//usually only contain a name and a value, so let's get easy access to them by their name.
for (Cookie _Cookie : _CookieList){
_CookieMap.put(_Cookie.getName(), _Cookie.getValue());
}
message.setProperty("incomingCookieMap", _CookieMap, PropertyScope.SESSION);
} catch (URISyntaxException e) {
e.printStackTrace();
}
return message;
}
}
Then there is this flow example which shows how to use this code snippet.
It contains a listener that sets some cookies, forwards it to a "proxy", which will read the cookies, but also forward the request to another endpoint, making it a transparent proxy, but which does read the cookies in the process.
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:json="http://www.mulesoft.org/schema/mule/json"
xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking"
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="EE-3.6.0"
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://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd">
<custom-transformer class="transformers.CookieGrabber"
name="MyCookieTranformer"
doc:name="Java"/>
<http:listener-config name="HTTP_Configuration_CookieHandlerExample"
host="0.0.0.0"
port="8080"
doc:name="HTTP Listener Configuration"/>
<http:request-config name="HTTP_Request_Configuration"
host="localhost"
port="8080"
doc:name="HTTP Request Configuration"/>
<flow name="CookieSetterFlow">
<http:listener config-ref="HTTP_Configuration_CookieHandlerExample"
path="/setCookies/*"
doc:name="setCookies"
doc:description="Call this module by entering http://localhost:8080/setCookie"/>
<message-properties-transformer doc:name="Set the cookies"
doc:description="Set some random cookies in the header">
<add-message-property key="Cookie"
value="token=abcde; name=dennis"/>
</message-properties-transformer>
<http:request config-ref="HTTP_Request_Configuration"
path="/proxyCookie"
method="GET"
doc:name="call proxyCookies"
doc:description="Invoke the cookieReceiver with the cookies we've just set. Note the failure status code validator with a non-existing http code. It's a nasty bug, but it works like this...">
<http:failure-status-code-validator values="00000"/>
</http:request>
</flow>
<flow name="CookieProxyFlow">
<http:listener config-ref="HTTP_Configuration_CookieHandlerExample"
path="/proxyCookie"
doc:name="proxyCookies"
doc:description="This connector will proxy the cookieReceiver"/>
<transformer ref="MyCookieTranformer"
doc:name="GrabCookies"
doc:description="Use our custom transformers.CookieGrabber class to put the cookies in a nice java.util.List in a session variable."/>
<logger message="CookieProxy: Value of cookie "token": "#[sessionVars.incomingCookieMap.get('token')]"."
level="INFO"
doc:name="Have a cookie!"
doc:description="Let get a cookie value, simply by referring the name of it as the key from our map"/>
<flow-ref name="copy-and-clean-headers"
doc:name="copy-and-clean-headers"
doc:description="Cope the headers and clean the Mule stuff from the headers to forward it clean to the receiver."/>
<set-property propertyName="host"
value="localhost"
doc:name="Set Host"
doc:description="Now not really necessary, but you'll probably want to set the hostname to the actual service endpoint."/>
<http:request config-ref="HTTP_Request_Configuration"
path="/receiveCookie"
method="GET"
doc:name="forward to receiveCookies"
doc:description="Invoke the cookieReceiver.">
<http:failure-status-code-validator values="00000"/>
</http:request>
<flow-ref name="copy-and-clean-headers"
doc:name="copy-and-clean-headers"
doc:description="Again copy the headers and clean the Mule http stuff."/>
</flow>
<sub-flow name="copy-and-clean-headers" >
<copy-properties propertyName="*"
doc:name="Copy All HTTP Headers"/>
<remove-property propertyName="Content-Length"
doc:name="Remove Content Length"/>
<remove-property propertyName="MULE_*"
doc:name="Remove MULE Properties"/>
<remove-property propertyName="X_MULE*"
doc:name="Remove X_MULE Properties"/>
<remove-property propertyName="http.*"
doc:name="Remove http Properties"/>
</sub-flow>
<flow name="CookieReceiverFlow">
<http:listener config-ref="HTTP_Configuration_CookieHandlerExample"
path="/receiveCookie"
doc:name="receiveCookies"
doc:description="This connector receives the cookies we've just set"/>
<transformer ref="MyCookieTranformer"
doc:name="GrabCookies"
doc:description="Use our custom transformers.CookieGrabber class to put the cookies in a nice java.util.List in a session variable."/>
<logger message="CookieReceiver: Value of cookie "token": "#[sessionVars.incomingCookieMap.get('token')]". Yep, still there :)"
level="INFO"
doc:name="Have a cookie!"
doc:description="Let get a cookie value, simply by referring the name of it as the key from our map"/>
<set-payload value="#[sessionVars.incomingCookieList.toArray(String)]"
doc:name="Put CookieList to payload"
doc:description="Put the session vairable List that contains the cookies in the payload"/>
<json:object-to-json-transformer returnClass="java.lang.String"
doc:name="Object to JSON"
doc:description="Convert our payload to a JSON object"/>
</flow>
</mule>
You can test it by running it and opening this page: http://localhost:8080/setCookies
Hope this helps.
You can fetch the cookies with:
#[headers:INBOUND:cookie] or #[message.inboundProperties['cookie']]

Mule HTTP POST `form-data` conversion to Map

My mule application is receiving a HTTP POST request with the Content-Type as multipart/form-data. I tried to use a custom transformer but do not know how to access the paramters as the object is of class ContentLengthInputStream.
How do I access the form parameters?
I want to convert the parameters into a map. How do I do this?
you can use #[message.inboundAttachments[payload] in a flow, for example, to send a http outbound endpoint:
<message-properties-transformer doc:name="Message">
<add-message-property key="Content-type" value="multipart/form-data/>
</message-properties-transformer>
<http:outbound-endpoint exchange-pattern="request-response" method="POST" doc:name="HTTP" address="http://localhost:9090" mimeType="multipart/form-data"/>
To receive can be used:
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8090" connector-ref="HTTP_HTTPS" doc:name="HTTP" contentType="multipart/form-data"/>
<logger message="#[message.inboundAttachments[payload]]" level="ERROR" doc:name="Logger"/>
You can use a transformer(AbstractMessageTransformer) and get the payload with:
DataHandler inboundAttachment = message.getInboundAttachment("AttachmentName");

MuleESB - get file from http post

In Mule I need to manipulate via java an xlsx file sent via http post.
How can I get the file posted via java?
I thought it was reachable via Mule message but
eventContext.getMessage().getOutboundAttachmentNames()
and neither
eventContext.getMessage().getInboundAttachmentNames()
give results.
Any ideas?
to make http post test I use curl in this way:
curl --form upload=#filename --form press=OK http://localhost:8088/HttpController
The flow is simply something like this:
<flow name="xlsx_to_xls_converterFlow1" doc:name="xlsx_to_xls_converterFlow1">
<http:inbound-endpoint exchange-pattern="request-response" doc:name="HTTP" address="http://localhost:8088/HttpController"/>
<logger level="INFO" doc:name="Logger"/>
<component class="Convert_XLSXtoXLS" doc:name="Java"/>
</flow>
Thank you
UPDATED
To let the flagged solution work occurs to override extractPayloadFromHttpRequest of HttpMultipartMuleMessageFactory to choose the proper input file name.
In fact with the current HttpMultipartMuleMessageFactory implementation the file is uploaded only if input file name = "payload"
You need to configure your HTTP connector to handle multipart requests to receive them in attachments. Add the following inside its XML configuration:
<service-overrides messageFactory="org.mule.transport.http.HttpMultipartMuleMessageFactory"/>
( if you think this is cumbersome, please upvote https://www.mulesoft.org/jira/browse/MULE-6862 )
Putting a Java component behind an http:inbound-endpoint results in an InputStream as argument to the method in the component.
You have to work with the input stream or just put an echo in between:
<flow name="FileUpload" doc:name="FileUpload">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="9090" doc:name="HTTP"/>
<echo-component doc:name="Echo"/>
<component class="de.codecentric.basics.FileUploadComponent" doc:name="Java"/>
</flow>
The component has one method:
package de.codecentric.basics;
public class FileUploadComponent {
public String process(String message) {
System.out.println("message: " + message);
return "OK";
}
}
You still have to parse the multipart form data in this case.
Or try to use the REST component, see: http://www.javaroots.com/2013/05/createfileuploadmulejerseyrest.html

Resources