How to upload multiple files via REST over HTTP using Mule? - mule

I have a folder say "MyFiles" where I have lots of files. Now I need to upload those file via REST over HTTP . What will be the approach?
I tried the below but it is wrong
<flow name="testFlow1" doc:name="testFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" doc:name="HTTP"/>
<http:rest-service-component
serviceUrl="http://localhost:8280/rest/xyz"
httpMethod="POST">
</http:rest-service-component>
<http:endpoint host="localhost" port="5430" encoding="UTF-8"
method="POST" connector-ref="fileHttp" path="fileuploader" name="muleFileUploader">
</http:endpoint>
</flow>
Please help. Since the input folder will have multiple files, how can we achieve that also?
Thanks

Your flow doesn't use a file inbound endpoint and uses a generic (non-in non-out) HTTP endpoint so there's no way this can work.
Below is a configuration that successfully uploads files to an HTTP endpoint. I can not make it work without the object-to-byte-array-transformer (the same file gets polled over and over again - bug?), so I hope your files are not huge...
<flow name="fileUploader">
<file:inbound-endpoint path="/tmp/mule/in"
pollingFrequency="5000" moveToDirectory="/tmp/mule/done" />
<object-to-byte-array-transformer />
<http:outbound-endpoint address="http://..."
method="POST" exchange-pattern="request-response" />
</flow>

Related

Mule file inbound connector with poll scope

I'm trying to use mule inbound file connector with poll scope got error saying couldn't start endpoint. If I remove poll scope and use file connector with default polling and its working fine without any file path changes.
I was wondering why is Poll scope giving error? If file inbound connector not allowed to wrapped in poll scope, why anypoint studio showing poll scope in the wrap in option ?
I found similar question, but I didn't see detailed explanations.
Mule won't allow POLL message processor to read file using file Inbound?
Advance thanks for your response.
Use mule-module-requester https://github.com/mulesoft/mule-module-requester, together with the Poll Scheduler.
relevant posts: http://blogs.mulesoft.com/dev/mule-dev/introducing-the-mule-requester-module/
Another way is,
Set the FTP flow initialState="stopped", and let the poll scheduler start the flow. After the FTP processing, stop the flow again.
see sample code:
<ftp:connector name="FTP" pollingFrequency="1000"
validateConnections="true" moveToDirectory="/work/ftp/processed"
doc:name="FTP" />
<flow name="scheduleStartFTPFlow">
<poll doc:name="Poll">
<fixed-frequency-scheduler frequency="1"
timeUnit="MINUTES" />
<expression-component doc:name="START FTP FLOW"><![CDATA[if(app.registry.processFTPFlow.isStopped()){
app.registry.processFTPFlow.start();
}]]></expression-component>
</poll>
<logger message="Poll Logging: #[payload]" level="INFO"
doc:name="Logger" />
</flow>
<flow name="processFTPFlow" initialState="stopped">
<ftp:inbound-endpoint host="localhost" port="21"
path="/data/ftp" user="Sanjeet" password="sanjeet123" responseTimeout="10000"
doc:name="FTP" connector-ref="FTP" />
<logger message="Logging FTP #[payload]" level="INFO" doc:name="Logger" />
<expression-component doc:name="STOP FTP FLOW"><![CDATA[app.registry.processFTPFlow.stop();]]></expression-component>
</flow>
Please, provide SSCCE.
Based on your question you do not need Poll at all. File Connector already has this feature to check file periodically. Here is example which polls file every 0.123 seconds
<file:inbound-endpoint path="/tmp" responseTimeout="10000" doc:name="File" pollingFrequency="123"/>
My suggestion is to use the quartz connector beside the file connector and set the interval in the quartz connector. Or use the file connector itself having the poll frequency so no need to wrap the file in poll scope.
you can create a file endpoint in the global element section and then use mule requester to invoke that endpoint inside a poll scope.
<file:connector name="File1" autoDelete="true" streaming="true" validateConnections="true" doc:name="File"/>
<file:endpoint connector-ref="File1" name="File" responseTimeout="10000" doc:name="File" path="/"/>
<flow name="pocforloggingFlow1">
<poll doc:name="Poll">
<mulerequester:request resource="File" doc:name="Mule Requester"/>
</poll>
</flow>

Mule ESB: How to achieve unlimited Retry till the consuming Service is up and running

I'm not sure how to apply logic to handle this issue.
I have a simple flow, Where I'm consuming the service in between the flow. I have tried until successful, but it required Max retries field( but I dont want to limit my retry by giving any number). To my scenario, I'm not sure when my consuming service is up, But need to retry until the service up and running ( not required retry exhausted). Could anyone suggest to handle the scenario.
<flow name="newFlow1" doc:name="newFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="ttt" doc:name="HTTP"/>
<byte-array-to-string-transformer doc:name="Byte Array to String"/>
<logger message="**********test****#[payload]" level="INFO" doc:name="Logger"/>
<until-successful doc:name="Until Successful">
<http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="8089" path="new" method="POST" doc:name="HTTP"/>
</until-successful>
<set-payload value="'Return Response'" doc:name="Set Payload"/>
</flow>
Also tried Max Retries in until successful as '-1'( to make as unlimited retry) but it is not accepting the negative value.
Tried using HTTP connector retry connection strategy(but it seems to be work for JMS or JDBC).
Could you please anyone suggest to handle this issue.
Thanks in advance.
Edited:
<http:connector name="HttpConnector" doc:name="HTTP-HTTPS">
<reconnect-forever />
</http:connector>
<flow name="new1Flow1" doc:name="new1Flow1">
<http:inbound-endpoint exchange-pattern="request-response" doc:name="HTTP" path="ttt" responseTimeout="30000" host="localhost" port="8081" />
<logger message="***entered***" level="INFO" doc:name="Logger"/>
<http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="8089" path="new" connector-ref="HttpConnector" method="POST" doc:name="HTTP"/>
<logger message="**Http StatusCode***#[message.inboundProperties['http.status']]" level="INFO" doc:name="Logger"/>
</flow>
It is not doing retry, since the service is down I could see the following error message in console for one time only.( But we should get multiple times the error message in console until service up)
Failed to route event via endpoint: DefaultOutboundEndpoint{endpointUri=http://localhost:8089/new, connector=HttpConnector
Please suggest.
You can first define a http Connector which will have a property of reconnecting forever
<http:connector name="HttpConnector" >
<reconnect-forever frequency="2000" />
</http:connector>
then you can have your inbound-or outbound endpoint use that connector reference
like this
<http:inbound-endpoint connector-ref="HttpConnector" .../>
or
<http:outbound-endpoint connector-ref="HttpConnector" .../>
Hope this helps!
Good luck!

How to Intercept incoming call in Mule

Hi I am working with Mule Any Point platform i am using composite source which is listening from HTTP and JMS both. I want to identify the incoming call coming from HTTP or JMS and i want to print using the logger. How to do that ?
Try the following way of using logger inside your endpoints.
<composite-source doc:name="Composite Source">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" doc:name="HTTP">
<logger message="Request coming from HTTP endpoint."></logger>
<set-variable value="HTTP" variableName="myVar"></set-variable>
</http:inbound-endpoint>
<jms:inbound-endpoint doc:name="JMS" queue="in">
<logger message="Request coming from JMS endpoint."></logger>
<set-variable value="JMS" variableName="myVar"></set-variable>
</jms:inbound-endpoint>
</composite-source>
In the flow when you have to chekc a condition, you can use the flow variable "myVar" to check whether the message came from HTTP or JMS endpoint.
Hope this helps.

MuleESB flow, why do I get two files outputted?

I'm trying to get one record from MongoDB and put it into a file, but I get two files, why is that? I thought that these would execute in a sequence and each step in the flow would take the data from the previous step, am I wrong?
<flow name="test1Flow2" doc:name="test1Flow2">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" doc:name="HTTP"/>
<mongo:find-one-object
config-ref="Mongo_DB" collection="my_collection" doc:name="Mongo DB"
query-ref="#[string:{ }]" >
</mongo:find-one-object>
<mongo:dbobject-to-json doc:name="Mongo DB"/>
<file:outbound-endpoint path="/somewhere" responseTimeout="10000" doc:name="Mongo DB"/>
</flow>
I go to this URL to trigger its execution.
http://localhost:8081/
Thanks, Philip
Try setting a path attribute for the http inbound endpoint, you are quite likely experiencing a favicon.ico request sent by your browser along with the http request you actually want to do.

How to rectify the issue with the below flow?

I have a mule flow as under
<flow name="flow1" doc:name="f1">
<file:inbound-endpoint path="C:\input" responseTimeout="10000"
doc:name="File" />
</flow>
<flow name="flow2" doc:name="f2">
<http:inbound-endpoint address="http://localhost:8080"
doc:name="HTTP" exchange-pattern="request-response" />
<flow-ref name="flow1" doc:name="Flow Reference" />
<file:outbound-endpoint path="C:\outputfile"
responseTimeout="10000" doc:name="File" />
</flow>
I am trying to move/upload multiple files from source to destination (can be anything e.g. FTP or File outbound etc..) by using the flow.
The reason for doing in this way is that I want to invoke the job from CLI(Command Line Interface) using CURL.
But it is not working....
Edited
I need to pick up some files(multiple files) from a particular folder located in my hard drive. And then move those to some outbound process which can be FTP site or some other hard drive location.
But this flow needs to be invoked from CLI.
Edited (Based on David's answer)
I now have the flow as under
<flow name="filePickupFlow" doc:name="flow1" initialState="stopped">
<file:inbound-endpoint path="C:\Input" responseTimeout="10000" doc:name="File"/>
<logger message="#[message.payloadAs(java.lang.String)]" level="ERROR" />
</flow>
<flow name="flow2" doc:name="flow2">
<http:inbound-endpoint address="http://localhost:8080/file-pickup/start" doc:name="HTTP" exchange-pattern="request-response"/>
<expression-component>
app.registry.filePickupFlow.start();
</expression-component>
<file:outbound-endpoint path="C:\outputfile" responseTimeout="10000" doc:name="File"/>
</flow>
I am getting couple of problems
a) I am getting an error that - Attribute initialState is not defined as a valid property of flow
However, if I remove that attribute, the flow continues without waiting for "http://localhost:8080/file-pickup/start" to fire up.
b) The files are not moved to the destination folder
So how can I do so?
You can't reference a flow that has an inbound endpoint in it because such a flow is already active and consuming events from its inbound endpoint so you can't invoke it on demand.
The following, tested on Mule 3.3.1, shows how to start a "file pickup flow" on demand from an HTTP request.
<flow name="filePickupFlow" initialState="stopped">
<file:inbound-endpoint path="///tmp/mule/input" />
<!-- Do something with the file: here we just log its content -->
<logger message="#[message.payloadAs(java.lang.String)]" level="ERROR" />
</flow>
<flow name="filePickupStarterFlow">
<http:inbound-endpoint address="http://localhost:8080/file-pickup/start"
exchange-pattern="request-response" />
<expression-component>
app.registry.filePickupFlow.start();
</expression-component>
<set-payload value="File Pickup successfully started" />
</flow>
HTTP GETting http://localhost:8080/file-pickup/start would then start the filePickupFlow, which in turn will process the files in /tmp/mule/input.
Note that it is up to you to configure the file:connector for what behavior it must have for files it processes, either deleting them or moving them to another directory are two main options.
I guess in this case a File inbound to read a file on demand will not be helpful.
Please try if the follwoing way.
<flow name="flow1" doc:name="f2">
<http:inbound-endpoint address="http://localhost:8080"
doc:name="HTTP" exchange-pattern="request-response" />
<component>
<spring-object bean="fileLoader"></spring-object>
</component>
<file:outbound-endpoint path="C:\outputfile"
responseTimeout="10000" doc:name="File" />
</flow>
So the Custom component will be a Class which reads the file from your specified location.
Hope this helps.
You can use Mule Requester for a clean solution. See the details in the blog entry Introducing the Mule Requester.