I have the following flow:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:json="http://www.mulesoft.org/schema/mule/json" xmlns:db="http://www.mulesoft.org/schema/mule/db" 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.5.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/db http://www.mulesoft.org/schema/mule/db/current/mule-db.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">
<db:generic-config name="Generic_Database_Configuration" url="jdbc:db2://localhost:50000/TEST:user=instuid;password=instpw;" driverClassName="com.ibm.db2.jcc.DB2Driver" doc:name="Generic Database Configuration"/>
<flow name="test2Flow1" doc:name="test2Flow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" doc:name="HTTP"/>
<db:select config-ref="Generic_Database_Configuration" doc:name="Database" doc:description="test">
<db:parameterized-query><![CDATA[SELECT SUM(BAL) FROM xxxx.ACCT]]></db:parameterized-query>
</db:select>
<json:object-to-json-transformer doc:name="Object to JSON"/>
</flow>
</mule>
The flow words well, and as you can see the JSON object converts the Database object to the following:
(A JSON arry with a single object):
[{"1":444}]
Notice that the 444 is a numeric value (it does not have quotes around it).
What I want to do
Create a simple JSON structure without an array
Change the 444 from a numeric value to a string value
Make it look something like: (placing the 444 into another structure)
{ "Total" : "444", "Date" : "14/07/14" }
I know that to get the system date, I perform the following:
#[server.dateTime.format('dd/MM/yy')]
... and I know to get the 444 value from the original string, I performed the following:
$..1
But I do not know what to do next.
Now that I used a JSON object to view the results of the database connector, what object do I do next to create my new structure.
Do I use another JSON object, how would I structure the expression ?
To write all numbers as strings you can set it on the Jackson object mapper and reference that custom object mapper from your transformer:
<spring:beans>
<spring:bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper" />
<spring:bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<spring:property name="targetObject" ref="jacksonObjectMapper" />
<spring:property name="targetMethod" value="configure" />
<spring:property name="arguments">
<spring:list>
<spring:value>WRITE_NUMBERS_AS_STRINGS</spring:value>
<spring:value>true</spring:value>
</spring:list>
</spring:property>
</spring:bean>
</spring:beans>
<flow name="flow1" doc:name="flow1">
...
<json:object-to-json-transformer mapper-ref="jacksonObjectMapper" />
...
</flow>
However this will dot it for all number fields. You might have to write a custom serializer for specific behaviour.
As for unwrapping the array. Not sure you can do this via the object mapper with the jackson version mule uses. But for this case, if your always just getting one result back from the query - you could possibly just unfold the array before the json transformer
<set-payload value="#[payload[0]]">
<json:object-to-json-transformer mapper-ref="jacksonObjectMapper" />
A simple way of doing is to use Mule's Expression Transformer.
You need to extract the values from your JSON array and store it into some variables like the following :-
<json:json-to-object-transformer returnClass="java.util.List" doc:name="JSON to Object" />
<set-variable variableName="Total" value="#[message.payload[0].1]" doc:name="Variable" />
Now, your variable Total will contain the value 444
Next step is to store your Date into some other variable as follows :-
<set-variable variableName="Date" value="#[server.dateTime.format('dd/MM/yy')]" doc:name="Variable" />
Now, if these 2 steps are done, then you can create your required JSON in a very easy way using Expression Transformer as follows :-
<expression-transformer
expression="#[[
'Total': flowVars['Total'].toString(),
'Date': flowVars['Date']
]]" doc:name="Expression" />
<json:object-to-json-transformer doc:name="Object to JSON" />
This will produce and structure your required JSON :- {"Date":"12/08/15","Total":"444"} in a very easy way
Related
Mule ESB
I am trying to convert a Hello World program into a program that will accept a JSON object, examine the data, and route the execution accordingly.
Below is a copy of my flow:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:json="http://www.mulesoft.org/schema/mule/json" version="EE-3.5.0" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:core="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:spring="http://www.springframework.org/schema/beans" 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/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd">
<json:object-to-json-transformer name="Object_to_JSON" doc:name="Object to JSON"/>
<flow doc:name="HelloWorldFlow1" name="HelloWorldFlow1">
<http:inbound-endpoint doc:description="This endpoint receives an HTTP message." doc:name="HTTP" exchange-pattern="request-response" host="localhost" port="8081" contentType="application/json"/>
<echo-component doc:name="Echo"/>
</flow>
</mule>
I see the object-to-json in the code, which I believe is configured from the
HTTP Node->HTTP Settings->content type, which is set to
application/json
So I assume that the incoming object is in JSON format once within the flow, with no fursther Object to JSON nodes required.
I am sending the following string to the flow:
{ "uid" : "ABCxxx" }
What I am trying to achieve to get a node that will examine and verify that the first three letters of the uid is "ABC", and if so send it down one path, but if the first three characters of the uid does not equal "ABC", to go down another path., sort of like a IF statement with a true and a false configtion,
The following is a Pseudo code example
IF uid[3] == "ABC"
GOTO Database Connector
else
GOTO JSON-TO-OBJECT Transformer
My question is: Whhich node should I use to perform this, should I use an Expression filter or other
... and how do I write that in JSAONPath (or other)
(Does Mule ESB perform this sort of thing?)
Th json evaluator that executes JsonPath in mule is deprecated in favor of MEL. The preferred approach now is to convert json to an object and query the object instead. One of the simplest approaches is to convert the json to the map and use MEL to query the map. Like so:
<json:json-to-object-transformer returnClass="java.util.HashMap" />
<choice>
<when expression="#[payload.uid == 'ABC']">
</when>
</choice>
More info here: http://www.mulesoft.org/documentation/display/current/Mule+Expression+Language+Tips
You can also <json:json-to-object-transformer returnClass="java.lang.Object" /> alternatively
and then
<choice>
<when expression="#[message.payload.uid == 'ABC']">
I need to insert .csv file into MYSQL database. All the examples on the web, give me "Deprecated Database" and then no solutions!
The HTML inbound endpoint is to send the csv file using postman plugin (chrome). when running the app, the console is showing this warning:
org.mule.routing.ExpressionSplitter: Splitter returned no results. If this is not expected, please check your split expression
even when I add a splitter after the Byte Array to String, and the expression is #[xpath('//item')], it keeps showing same warning!
I have MuleESB enterprise. All connections with database is correct.
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:jdbc-ee="http://www...
<db:mysql-config name="MySQL_Configuration" host="localhost"
port="3306" database="dbflow"
doc:name="MySQL Configuration" user="root"/>
<data-mapper:config name="CSV_To_XML" transformationGraphPath="csv_to_xml.grf" doc:name="CSV_To_XML"/>
<jdbc-ee:mysql-data-source name="MySQL_Data_Source" user="User" password="Pass" url="jdbc:mysql://localhost:3306/dbflow" transactionIsolation="UNSPECIFIED" doc:name="MySQL Data Source"/>
<jdbc-ee:connector name="Database" dataSource-ref="MySQL_Data_Source" validateConnections="true" queryTimeout="-1" pollingFrequency="0" doc:name="Database"/>
<flow name="dbFlow1" doc:name="dbFlow1">
<http:inbound-endpoint exchange-pattern="one-way" host="localhost" port="8084" path="csv" doc:name="HTTP"/>
<data-mapper:transform config-ref="CSV_To_XML" doc:name="CSV To XML"/>
<byte-array-to-string-transformer doc:name="Byte Array to String"/>
<foreach collection="#[xpath('//info')]" doc:name="For Each">
<mulexml:dom-to-xml-transformer doc:name="DOM to XML"/>
<db:insert config-ref="MySQL_Configuration" doc:name="Database">
<db:parameterized-query><![CDATA[INSERT INTO `dbflow`.`user_table`
(`current_date`,
`serialnumber`,
`gender`,
`fullname`,
`birthdate`,
`email`,
`mobilnumber`,
`address`)
VALUES
(#[xpath://date],
#[xpath://serialnumber],
#[xpath://gender],
#[xpath://fullname],
#[xpath://birthdate],
#[xpath://email],
#[xpath://mobilenumber],
#[xpath://address]
);]]></db:parameterized-query>
</db:insert>
</foreach>
</flow>
</mule>
From the discussions, it seems the core issue is that the HTTP POSTed content ends up producing this XML:
<?xml version="1.0" encoding="UTF-8"?>
<infos/>
which explains why the for-each doesn't produce anything.
The solution consists in HTTP POSTing a valid non-empty CSV entity.
I am new for MuleESB. I don't have much knowledge about flow. I couldn't find proper documentation for Mule. I am trying to fetch the data from database using below code, but I am unable fetch the data. There is no error shown, so I dont know what to do. Is my flow correct?
Here's my flow config.
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:jdbc-ee="http://www.mulesoft.org/schema/mule/ee/jdbc" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:json="http://www.mulesoft.org/schema/mule/json" xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml" 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.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/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.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/jdbc http://www.mulesoft.org/schema/mule/ee/jdbc/current/mule-jdbc-ee.xsd
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd">
<jdbc-ee:postgresql-data-source name="PostgreSQL_Data_Source" user="youtilitydba" password="Youtility11" url="jdbc:postgresql://localhost:5432/sample" transactionIsolation="UNSPECIFIED" doc:name="PostgreSQL Data Source"/>
<jdbc-ee:connector name="Database" dataSource-ref="PostgreSQL_Data_Source" validateConnections="true" queryTimeout="-1" pollingFrequency="0" doc:name="Database"/>
<flow name="selectfromdbFlow1" doc:name="selectfromdbFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="selectdb" doc:name="HTTP"/>
<json:json-to-object-transformer returnClass="java.util.Map" doc:name="JSON to Object"/>
<jdbc-ee:outbound-endpoint exchange-pattern="one-way" queryKey="SELECT" queryTimeout="-1" connector-ref="Database" doc:name="Database">
<jdbc-ee:query key="SELECT" value="select firstname,lastname,id from users where id =#[message.payload.id]"/>
</jdbc-ee:outbound-endpoint>
<response>
<http:response-builder status="200" contentType="application/json" doc:name="HTTP Response Builder"/>
</response>
<set-payload value="#[payload]" doc:name="Set Payload"/>
<echo-component doc:name="Echo"/>
</flow>
</mule>
I am sending request from curl client like this
curl -H "Content-Type: application/json" -d '{"id":"5"}' http://192.168.25.24:8081/selectdb
It doesn't provide and response back.
I am expecting a response like the one below.
{"Body":{"Datalist":{"firstname":"ff","lastname":"ggg","id":"5"}},"Status":"200"}}
Please help me acheive this.
Even the logger statement is not printing
<logger message="message of payload#[message.payload]" level="INFO" doc:name="Logger"/>
Appreciate any help.
You can better use <json:json-to-object-transformer returnClass="java.lang.Object" doc:name="JSON to Object"/> after http:inbound-endpoint and make sure if you are getting the id value from request and after payload after db
Now, if you are getting the data from your db and able to print it using a logger after db using
<logger message="message of payload #[message.payload]" level="INFO" doc:name="Logger"/>
You can explicitly set your response to your client in following way :-
<http:response-builder status="200" contentType="application/json" doc:name="HTTP Response Builder">
<set-payload value="#[message.payload]" doc:name="Set Payload"/>
</http:response-builder>
and you can remove the <response/> tag from your flow, as you are setting your response payload using <http:response-builder/> as above
I can't answer your question fully, but can tell you few easy ways to inspect your muleMessage.
the first and easiest way is to place a script transformer like this:
<script:transformer>
<script:script engine="groovy">
<script:text>
System.out.println(payload);
return payload;
</script:text>
</script:script>
</script:transformer>
namespace: xmlns:script="http://www.mulesoft.org/schema/mule/scripting"
schemaLocation: http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd
second option and harder one would be creating custom transformer. U'll need to create a java class, extend the AbstractMessageTransformer. Then debug your project and see what's the message
hope, this will help
Couldn't get the complete issue you are facing. From the post I can see there are few changes to be made.
As you are looking for data back from Select Query change the exchange-pattern on the JBDC:Outbound to request-response
<jdbc-ee:outbound-endpoint exchange-pattern="request-response" queryKey="SELECT" queryTimeout="-1" connector-ref="Database" doc:name="Database">
Also there is no need of the <set-payload> at the end of the flow. As the payload is already available in the message, this is a redundant statement.
In the logger try using #[payload] as it is more simple to print your payload (response from JBDC query)
About documentation, MuleSoft website is the best place to find documentation about mule They have a detailed documentation for most of the things of Mule.
Mule User Guide and Documentation
Hope this helps.
i try this example : Using Mule Studio to read CSV step by step but but content of csv donot copy to database . i have not any errors i left my console and myflow :
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:file="http://www.mulesoft.org/schema/mule/file" xmlns:jdbc="http://www.mulesoft.org/schema/mule/jdbc" 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.3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd
http://www.mulesoft.org/schema/mule/jdbc http://www.mulesoft.org/schema/mule/jdbc/current/mule-jdbc.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 ">
<configuration doc:name="Configuration">
<expression-language autoResolveVariables="true">
<import class="org.mule.util.StringUtils" />
</expression-language>
</configuration>
<jdbc:mysql-data-source name="MySQL_Data_Source" user="roor" url="jdbc:mysql://localhost:3306/csv" transactionIsolation="UNSPECIFIED" doc:name="MySQL Data Source" password="1234"/>
<jdbc:connector name="Database" dataSource-ref="MySQL_Data_Source" validateConnections="true" queryTimeout="-1" pollingFrequency="0" doc:name="Database">
<jdbc:query key="InsertRecord" value="INSERT INTO "tblFamily"("Title", "FirstName", "LastName") VALUES (#[message.payload[0]],#[message.payload[1]],#[message.payload[2]])"/>
</jdbc:connector>
<flow name="csvFlow1" doc:name="csvFlow1">
<!-- Step 1: CSV file source -->
<file:inbound-endpoint path="C:\Users\masoudy\Downloads\Compressed\Resoes" pollingFrequency="5000" doc:name="Source"/>
<!-- Step 2: Convert between object arrays and strings -->
<object-to-string-transformer doc:name="Object to String"/>
<splitter expression="#[StringUtils.split(message.payload, '\n\r')]" doc:name="Splitter"/>
<expression-transformer expression="#[StringUtils.split(message.payload, ',')]" doc:name="Expression"/>
<jdbc:outbound-endpoint exchange-pattern="one-way" queryTimeout="-1" doc:name="Destination" connector-ref="Database" queryKey="InsertRecord"/>
</flow>
</mule>
my console:
.....
**********************************************************************
* Application: csv *
* OS encoding: Cp1256, Mule encoding: UTF-8 *
* *
* Agents Running: *
* JMX Agent *
**********************************************************************
INFO 2013-04-22 14:55:54,437 [main] org.mule.module.launcher.DeploymentService:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Started app 'csv' +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
console
csv
I could take good result and csv file converted to database.
I had 2 mistakes:
after run program, .csv file cleaned from path and I did not and run the program again without .csv file
name of fields in queries xml was difference to name of columns in database
I've been struggling through SO and the Mule forums but can't find a solution that works. The esb takes in a single request containing an id, which creates an XML payload that is composed a list of related ids. This XML payload is then split and sent to a transformer that takes each related id to get some meta data. The results are then supposed to be combined together to make an XML response. The problem I am having is that no matter how I transform the final result set, I always get back the document with an encapsulating string "??sr)java.util.concurrent.CopyOnWriteArrayListx]....""x
Any ideas/comments would be greatly appreciated.
Here is the mule-config I am using:
<http:connector name="HttpConnector" doc:name="HTTP\HTTPS"/>
<expression-transformer name="ExtractId" doc:name="Expression">
<return-argument evaluator="xpath" expression="//string[1]"/>
</expression-transformer>
<flow name="myFlow1" doc:name="myFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="incoming/path/" connector-ref="HttpConnector" doc:name="HTTP"/>
<custom-transformer encoding="UTF-8" class="mycomponents.transformers.SubscriberRequestTransformer" doc:name="Create Hub Id Requests"/>
<mulexml:object-to-xml-transformer doc:name="Object to XML"/>
<splitter evaluator="xpath" expression="//entry/list/string" enableCorrelation="ALWAYS" doc:name="Splitter"/>
<transformer ref="ExtractId" doc:name="Transformer Reference"/>
<logger message="#[payload:]" level="INFO" doc:name="Logger"/>
<custom-transformer encoding="UTF-8" class="mycomponents.transformers.HubQueryProcessor" doc:name="Create Hub Id Requests"/>
<collection-aggregator />
<component class="mycomponents.TopicResponseAggregatorComponent" doc:name="Collect requests" />
<logger message="Aggregated Content (#[groovy:payload.size()] elements): \n#[payload:]" level="INFO" doc:name="Logger"/>
<logger message="#[payload:]" level="INFO" doc:name="Logger"/>
</flow>
I've resolved the issue. Although I don't quite understand why it's different but I'm assuming it has to do with some of the mule "magic". I split up the flow into multiple flows which is what I was eventually going to do anyways. However, by doing this the problem went away.
FYI: here's the updated flow:
<flow name="myFlow1" doc:name="myFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="url/for/service/" connector-ref="HttpConnector" doc:name="HTTP"/>
<flow-ref name="createHubIdRequestsFlow" doc:name="Map To Hub Ids" doc:description="Takes in the situation id passed in by the client. Does the query lookup versus the content mapping tables. creates the correspondng requests for meta data information to the provider(s)"/>
<flow-ref name="getTopicRequests" doc:name="Process Provider Reponses" doc:description="For each JSON response returned from the provider, transform it into an XML representation of that data"/>
<flow-ref name="buildResponseFlow" doc:name="Build final response" doc:description="piece all the messages together into a single object as a string"/>
<response>
<message-properties-transformer>
<add-message-property value="text/xml" key="Content-Type" />
</message-properties-transformer>
</response>
</flow>
By default, the message properties transformer stores new properties in the "invocation" scope. You need to set the content-type on the "outbound" scope so it is used by the inbound HTTP endpoint in its response phase.
Try this:
<response>
<message-properties-transformer scope="outbound">
<add-message-property value="text/xml" key="Content-Type" />
</message-properties-transformer>
</response>