How to set content type = "application/json" in mule.? - content-type

I have a HTML file which consists of a Form and it takes certain parameters from the User and when the URL is hit, a Mule service (written in Java) is called and it returns a JSON string. Now how can I set Content-type = application/json in either Mule or Java, so that browser know that it is getting a JSON?
My Mule config file is :
<custom-transformer name="HttpParams" class="org.mule.transport.http.transformers.HttpRequestBodyToParamMap" />
<message-properties-transformer name="HttpResponse">
<add-message-property key="Content-Type" value="application/json" />
<add-message-property key="http.status" value="303" />
</message-properties-transformer>
<flow name="jcars">
<http:inbound-endpoint address="http://localhost:11221/jcars" transformer-refs="HttpParams" responseTransformer-refs="HttpResponse">
<not-filter>
<wildcard-filter pattern="/favicon.ico"/>
</not-filter>
</http:inbound-endpoint>
<component class="defaults.basicapp.jcars"/>
</flow>
And my Java class is (Jcars) :
public String onEvent(Object obj){
String json = "{{"id":0,"model":"suzuki","make":"2002","ps":true,"price":101.2,"bhp":12.6},{"id":0,"model":"suzuki","make":"2003","ps":true,"price":101.2,"bhp":12.6},{"id":0,"model":"suzuki","make":"2004","ps":true,"price":101.2,"bhp":12.6},{"id":0,"model":"suzuki","make":"2005","ps":true,"price":101.2,"bhp":12.6},{"id":0,"model":"suzuki","make":"2006","ps":true,"price":101.2,"bhp":12.6}}";
return json;
}
The browser is displaying the string as it is. It does not know that the content type is application/json. What should I do?

Add a response message properties transformer in your flow in order to set the content type:
<response>
<message-properties-transformer>
<add-message-property key="Content-Type" value="application/json" />
</message-properties-transformer>
</response>

Related

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");

Mule ESB - How to call a API via HTTP POST method (sending parameters along)

Its me again.
I am trying to create a flow that will post a a job opening to a job portal. They expose their API via a Post method. I am not sure how to pass the values to the HTTP end-point.
This is just a testing sample with hard coded values in it. when it works will I have the flow pick-up the values from a database.
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:wmq="http://www.mulesoft.org/schema/mule/ee/wmq" 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.4.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
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/ee/wmq http://www.mulesoft.org/schema/mule/ee/wmq/current/mule-wmq-ee.xsd">
<http:connector name="HTTP_CONFIG" cookieSpec="netscape" validateConnections="false" sendBufferSize="0" receiveBufferSize="0" receiveBacklog="0" clientSoTimeout="100000" serverSoTimeout="100000" socketSoLinger="0" proxyHostname="pta-proxy.work.co.za" proxyPort="3128" doc:name="HTTP\HTTPS" />
<flow name="career24Flow1" doc:name="career24Flow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8083" doc:name="HTTP" contentType="text/plain"/>
<message-properties-transformer doc:name="Set the post Values" >
<add-message-property key="apikey" value="XXXX"/>
<add-message-property key="integrationkey" value="567"/>
<add-message-property key="consultantemail" value="integrations#work.com"/>
<add-message-property key="title" value="Testing Mule API"/>
<add-message-property key="reference" value="33175"/>
<add-message-property key="jobtypeid" value="1"/>
<add-message-property key="closingdate" value="01/06/2014"/>
<add-message-property key="location" value="66"/>
<add-message-property key="salaryfrom" value="10000.00"/>
<add-message-property key="salaryto" value="20000.00"/>
<add-message-property key="salaryunitid" value="4"/>
<add-message-property key="description" value="Testing the Mule ESB to post to the portal"/>
<add-message-property key="companyname" value="CSIR"/>
<add-message-property key="sectorids" value="17"/>
<add-message-property key="applicationmethodid" value="2"/>
<add-message-property key="applicationurl" value="http://www.testing.com"/>
<add-message-property key="package" value="2"/>
</message-properties-transformer>
<http:outbound-endpoint exchange-pattern="request-response" host="api.work.com" port="80" method="POST" doc:name="Post on Career24" path="_integrations/httppost/vacancy.ashx" connector-ref="HTTP_CONFIG" contentType="application/x-www-form-urlencoded"/>
</flow>
</mule>
I get this back from the site so it seems the values are not being sent via the HTTP end-point.
ERROR:
- Field 'apikey', is required.
- Field 'integrationkey', is required.
- Field 'consultantemail', is required.
- Field 'title', is required.
- Field 'reference', is required.
- Field 'jobtypeid', is required.
- Field 'closingdate', is a required field.
- Field 'sectorids', is required.
- Field 'location', is required.
- Field 'description', is required.
- Field 'applicationmethodid', is required.
I have tried a "Message to HTTP Response" transformer as well but still no luck.
Thanks for the help.
Regards.
Jaco.
Using properties with http outbound endpoint will set them as http headers. Instead you need a payload of type Map to set them as POST variables.
Like this:
<set-payload value="#[['xxx':'yyy']]"/>

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

receiving and sending multipart/form-data in mule 3.2

I have problem in configuring Mule 3.2 which basically receive HTTP POST (multipart/form-data) and routing the payload and then send the payload by HTTP POST (multipart/form-data). How exactly to do that kind of task in Mule ?
Below are parts of my configuration
<flow name="UserBridgeFlow" doc:name="UserBridgeFlow">
<inbound-endpoint address="http://${local.server}/${user.context}/" exchange-pattern="request-response" connector-ref="STD_HTTP_CONNECTOR" doc:name="User Endpoint"/>
<echo-component doc:name="Echo"/>
<transformer ref="RouteTransformer" doc:name="Transformer Reference"/>
<response>
<message-properties-transformer overwrite="true" doc:name="Message Properties">
<add-message-property key="Access-Control-Allow-Origin" value="*"/>
</message-properties-transformer>
</response>
<response>
<echo-component doc:name="Echo"/>
</response>
<http:outbound-endpoint exchange-pattern="request-response" address="http://${user.server}/#[header:OUTBOUND:real.path]" doc:name="HTTP User"/>
<default-exception-strategy>
<processor-chain>
<logger level="INFO" doc:name="Logger"/>
</processor-chain>
</default-exception-strategy>
</flow>
With above configuration, my binary data is always corrupted when reaching the other endpoint and also I get this error in the browser (caller endpoint) "The character encoding of the plain text document was not declared. The document will render with garbled text in some browser configurations if the document contains characters from outside the US-ASCII range. The character encoding of the file needs to be declared in the transfer protocol or file needs to use a byte order mark as an encoding signature."
-- UPDATED CONFIGURATION --
<context:property-placeholder location="classpath:/mule.properties"/>
<custom-transformer class="id.co.zire.ebs.mule.transformer.RouteTransformer" name="RouteTransformer" doc:name="RouteTransformer"/>
<http:connector name="STD_HTTP_CONNECTOR" enableCookies="true" validateConnections="true" clientSoTimeout="20000" serverSoTimeout="10000" doc:name="HTTP\HTTPS">
<dispatcher-threading-profile maxThreadsActive="50" maxBufferSize="150"/>
<reconnect count="3" frequency="2000"/>
</http:connector>
<flow name="HTTPBridgeFlow" doc:name="HTTPBridgeFlow">
<composite-source>
<inbound-endpoint exchange-pattern="request-response" address="http://${local.server}/${user.context}/" encoding="ISO-8859-1" connector-ref="STD_HTTP_CONNECTOR" doc:name="User Endpoint"/>
<inbound-endpoint exchange-pattern="request-response" address="http://${local.server}/${cms.context}/" encoding="ISO-8859-1" connector-ref="STD_HTTP_CONNECTOR" doc:name="CMS Endpoint"/>
<inbound-endpoint exchange-pattern="request-response" address="http://${local.server}/${ads.context}/" encoding="ISO-8859-1" connector-ref="STD_HTTP_CONNECTOR" doc:name="Ads Endpoint"/>
</composite-source>
<echo-component doc:name="Echo"/>
<transformer ref="RouteTransformer" doc:name="Transform Header"/>
<set-property propertyName="http.method" value="#[header:INBOUND:http.method]" doc:name="Copy HTTP method"/>
<flow-ref name="HTTPResponseFlow" doc:name="HTTP Flow Reference"/>
</flow>
<sub-flow name="HTTPResponseFlow" doc:name="HTTPResponseFlow">
<logger message="Payload Output : #[message.payload]" level="INFO" doc:name="Logger"/>
<choice doc:name="Choice">
<when expression="message.inboundProperties['http.context.path'] contains '${user.context}'">
<processor-chain>
<http:outbound-endpoint exchange-pattern="request-response" address="http://${user.server}/#[message.inboundProperties['http.relative.path']]" responseTimeout="120000" doc:name="HTTP User"/>
</processor-chain>
</when>
<when expression="message.inboundProperties['http.context.path'] contains '${cms.context}'">
<processor-chain>
<http:outbound-endpoint exchange-pattern="request-response" address="http://${cms.server}/#[message.inboundProperties['http.relative.path']]" responseTimeout="120000" doc:name="HTTP CMS"/>
</processor-chain>
</when>
<when expression="message.inboundProperties['http.context.path'] contains '${ads.context}'">
<processor-chain>
<http:outbound-endpoint exchange-pattern="request-response" address="http://${ads.server}/#[message.inboundProperties['http.relative.path']]" responseTimeout="120000" doc:name="HTTP Ads"/>
</processor-chain>
</when>
</choice>
<echo-component doc:name="Echo"/>
<message-properties-transformer doc:name="Set Cross-Domain Request Allowed">
<add-message-property key="Access-Control-Allow-Origin" value="*"/>
<add-message-property key="Access-Control-Allow-Methods" value="GET, POST, OPTIONS"/>
<add-message-property key="Access-Control-Max-Age" value="1000"/>
<add-message-property key="Access-Control-Allow-Headers" value="Content-Type"/>
</message-properties-transformer>
</sub-flow>
OK, now I have change most of the configuration, now I have problem of passing the included binary data in the HTTP POST message body. Mule seems to be altering the bytes before passing it to the outbound endpoint. I have create a custom transformer to get the payload manually and parse the binary data from the payload (payload type is String by the way) but the retrieved binary data from payload is already altered. For example below is part of the original file bytes in hexadecimal:
ff d8 ff e0 00 10 4a 46 (ÿØÿà..JF)
but Mule converts into:
3f 3f 3f 3f 00 10 4a 46 (????..JF)
I think it is encoding issue, maybe Mule converts it automatically to UTF-8
-- RouteTransformer.java --
public class RouteTransformer extends AbstractMessageTransformer{
private static final String MULE_CONFIG = "/mule.properties";
private static final String CLIENT_IP = "MULE_REMOTE_CLIENT_ADDRESS";
private static final String CLIENT_IP_HEADER = "Client-Ip";
private static final String IP_REGEX = "/?((\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3}))(:(\\d{1,5}))?";
private final String[] PASSING_HEADER;
public RouteTransformer() throws IOException{
Properties prop = new Properties();
prop.load(getClass().getResourceAsStream(MULE_CONFIG));
PASSING_HEADER = prop.getProperty("passing-header").split("\\s*,\\s*");
}
public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException{
// Copy 'passing' header
for(int i=PASSING_HEADER.length; --i>=0; ){
String headerName = PASSING_HEADER[i];
Object val = message.getInboundProperty(headerName);
if(headerName.equals(CLIENT_IP)){
String s = (String) val;
Pattern p = Pattern.compile(IP_REGEX);
Matcher m = p.matcher(s);
if(!m.matches()) continue;
else{
headerName = CLIENT_IP_HEADER;
val = m.group(1);
}
}
if(val != null) message.setOutboundProperty(headerName, val);
}
// Routing message
String requestString = message.getInboundProperty("http.request");
String contextPath = message.getInboundProperty("http.context.path");
if(requestString != null && contextPath != null)
message.setOutboundProperty("http.real.path", requestString.substring(contextPath.length()));
return message;
}
}
-- Multipart/form-data example --
-----------------------------20037128598723
Content-Disposition: form-data; name="name"
Angga
-----------------------------20037128598723
Content-Disposition: form-data; name="adsImage"; filename="Penguins.jpg"
Content-Type: image/jpeg
ÿØÿà..JF -- and the rest of bytes --
I hope somebody can bring some solutions.
Thanks
In your content type you have to add charset=utf-8:
response.setContentType("application/json; charset=utf-8")
Content-Type: application/json; charset=utf-8
I'm wondering if the issue you're facing is related to the lack of content type (or its default value) on the outbound HTTP interaction.
Try adding a message properties transformer (or a copy properties message processor for 3.3.x users reading this) to copy the "Content-Type" property from the inbound scope to the outbound one.
Also, for strictness' sake, configure this endpoint to use the POST method.

How to Edit Default Mule Error message..?

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>

Resources