Multiple calls with mule to ODATA server to retrieve tables - mulesoft

I have to retrieve 20 tables from ODATA service with mule 3. The solution that I have created is using scatter gather to make these http request calls and the fetched payload is saved into files.
It works fine only it look not very elegant, because you see scatter gather with a lot of http request connectors. There is no ODATA connector for 3.9 mule and Foreach was not possible to loop into the calls. Do you guys have any idea how to solve it with less connectors or logic?
<flow name="proces-flow">
<poll doc:name="Poll">
<fixed-frequency-scheduler frequency="30000"/>
<logger message="start flow" level="INFO" doc:name="Logger"/>
</poll>
<scatter-gather doc:name="Scatter-Gather">
<http:request config-ref="HTTP_Request_Configuration" path="${http.cat.path}" method="GET" doc:name="HTTP"/>
<http:request config-ref="HTTP_Request_Configuration" path="${http.sub.path}" method="GET" doc:name="HTTP"/>
<http:request config-ref="HTTP_Request_Configuration" path="${http.sub2.path}" method="GET" doc:name="HTTP"/>
<http:request config-ref="HTTP_Request_Configuration" path="${http.sub3.path}" method="GET" doc:name="HTTP"/>
<http:request-config name="HTTP_Request_Configuration1" protocol="HTTPS" host="caller-test.service.com" port="443" basePath="/repo/v1/odata/Incidents?$filter=callDate gt 2019-09-01T08:00:00Z and callDate lt 2019-09-01T09:00:00Z" doc:name="HTTP Request Configuration">
</scatter-gather>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
payload]]></dw:set-payload>
</dw:transform-message>
<file:outbound-endpoint path="C:\Local\fileshare-service" outputPattern="output.json" responseTimeout="10000" doc:name="File"/>
<exception-strategy ref="" doc:name="Reference Exception Strategy"/>
</flow>
As you can see if I have to make 20 queries I have to add 20 calls. Because it's a ODATA I use the base path to add the hole query in it.
This works but, as I say, it's not the solution you want if the application will grow. For those how have query inside the request I have to create new http request configuration every time, because I use the base path to add variable etc and that can't be done in usual path.

Related

Implementing Sage Intacct API via Postman

I would like to get the invoice link from the purchase order implementing Sage Intacct API via Postman.
I suppose it can be done by following sequences(or by only one api request? not sure about this).
Order a purchase
Create a purchase receipt
Get an invoice link from it
Please refer to this API document (https://developer.intacct.com/api).
i.e. This is the body of a request to create a purchase transaction.
<?xml version="1.0" encoding="UTF-8"?>
<request>
<control>
<senderid>{{sender_id}}</senderid>
<password>{{sender_password}}</password>
<controlid>{{$timestamp}}</controlid>
<uniqueid>false</uniqueid>
<dtdversion>3.0</dtdversion>
<includewhitespace>false</includewhitespace>
</control>
<operation>
<authentication>
<sessionid>{{temp_session_id}}</sessionid>
</authentication>
<content>
<function controlid="{{$guid}}">
<create_potransaction>
<transactiontype>Purchase Requisition</transactiontype>
<datecreated>
<year>2013</year>
<month>6</month>
<day>19</day>
</datecreated>
<vendorid>1001</vendorid>
<referenceno>1234</referenceno>
<vendordocno>vendordocno001</vendordocno>
<datedue>
<year>2013</year>
<month>6</month>
<day>20</day>
</datedue>
<payto>
<contactname>Jameson Company</contactname>
</payto>
<exchratetype>Intacct Daily Rate</exchratetype>
<customfields/>
<potransitems>
<potransitem>
<itemid>75300GL</itemid>
<quantity>100</quantity>
<unit>Each</unit>
<price>1</price>
<locationid>MGMT-US</locationid>
<departmentid>IT</departmentid>
</potransitem>
</potransitems>
</create_potransaction>
</function>
</content>
</operation>
</request>
Thank you in advance.
You can download the Postman collection file (API) from the developer docs.
And then just refer to Purchasing/Purchasing Transactions/Create Transaction (Legacy).
You can change the body (SOAP) content.
I'm sure you can manage it.

How to get Parent Table "Record Id" (Auto generated id) of SalesForce in MuleSoft

I am trying to access parent "Record ID" (Auto generated ID) in a MULESOFT Flow and store it into child table of SalesForce and store that record id in one variable and pass it to child table through DataWeave Transformation. I am using one flow for this task. Can anyone please tell me how can i get parent table Record ID? Thanks.
Here is my flow Confi. XML file
<flow name="shoppingcartpocmcpostsfuserFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/customeruser" allowedMethods="POST" doc:name="HTTP"/>
<object-to-byte-array-transformer doc:name="Object to Byte Array"/>
<dw:transform-message doc:name="Transform Message" metadata:id="4851f81e-2a1b-4e5e-a34f-cc328e6dd23d">
<dw:input-payload mimeType="application/json"/>
<dw:set-payload><![CDATA[%dw 1.0
%output application/java
---
[{
Name: payload.ShoppingCartUser.ShoppingCartUserName,
FirstName__c: payload.ShoppingCartUser.FirstName,
LastName__c: payload.ShoppingCartUser.LastName,
EmailID__c: payload.ShoppingCartUser.EmailID,
PhoneNumber__c: payload.ShoppingCartUser.PhoneNumber,
CompanyName__c: payload.ShoppingCartUser.Company,
CustomerType__c: payload.ShoppingCartUser.Customer_Type
}]]]></dw:set-payload>
</dw:transform-message>
<sfdc:create config-ref="Salesforce__Basic_Authentication" type="MS_ShoppingCartUser__c" doc:name="Salesforce Connector for User Details">
<sfdc:objects ref="#[payload]"/>
</sfdc:create>
<object-to-string-transformer doc:name="Object to String"/>
<set-variable variableName="id" value="#[flowVars.id]" doc:name="Variable"/>
<dw:transform-message doc:name="Transform Message for User Address" metadata:id="4851f81e-2a1b-4e5e-a34f-cc328e6dd23d">
<dw:input-payload mimeType="application/json"/>
<dw:set-payload><![CDATA[%dw 1.0
%output application/java
---
[{
AddressLine1__c: payload.ShoppingCartUser.AddressLine_1,
AddressLine2__c: payload.ShoppingCartUser.AddressLine_2,
CountyName__c: payload.ShoppingCartUser.County,
City__c: payload.ShoppingCartUser.City,
Country__c: payload.ShoppingCartUser.Country,
State__c: payload.ShoppingCartUser.State,
ZipCode__c: payload.ShoppingCartUser.Zipcode,
EmailID__c: id
}]]]></dw:set-payload>
</dw:transform-message>
<sfdc:create config-ref="Salesforce__Basic_Authentication" type="MS_ShoppingCart__c" doc:name="Salesforce Connector for User Address">
<sfdc:objects ref="#[payload]"/>
</sfdc:create>
<object-to-string-transformer doc:name="Object to String"/>
</flow>
The sfdc:create operation will return a 'Result' https://docs.mulesoft.com/connectors/salesforce/salesforce-connector-reference-96#Result
It has an 'Id' field. You can access the id using 'payload.Id'
Note in your example you will need to remove the object-to-string to access it. It will also overwrite your payload. So you need to use an enricher if you need the same payload values in your second transform.

Mule - how to parse the JSON response of REST webservice and update database

I want to write a mule application which will read the database for unprocessed records, club them in JSON payload and then hit a REST webservice, REST webservice(Hosted on different server) will process the records and return the JSON output. Now I have to parse the JSON and update the database for the processed flag.
I am able to get the response from the REST webservice, I have used Byte array to string transform to log in the logger.
Do I need to write foreach component to process the payload one by one and update the database?
here is my configuration XML
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:oauth2="http://www.mulesoft.org/schema/mule/oauth2" xmlns:db="http://www.mulesoft.org/schema/mule/db" xmlns:json="http://www.mulesoft.org/schema/mule/json" 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"
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/json http://www.mulesoft.org/schema/mule/json/current/mule-json.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/oauth2 http://www.mulesoft.org/schema/mule/oauth2/current/mule-oauth2.xsd">
<db:mysql-config name="MySQL_Configuration" host="localhost" port="3306" user="root" database="my_db_name" doc:name="MySQL Configuration"/>
<http:request-config name="HTTP_Request_Configuration" protocol="HTTPS" host="example.net" port="8000" basePath="Salvage" doc:name="HTTP Request Configuration"/>
<flow name="cwg_clientFlow">
<poll doc:name="Poll">
<db:select config-ref="MySQL_Configuration" doc:name="Database">
<db:parameterized-query><![CDATA[SELECT * FROM cwg_ws_data WHERE SyncFlag = 0]]></db:parameterized-query>
</db:select>
</poll>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
<json:object-to-json-transformer doc:name="Object to JSON" encoding="UTF-8" mimeType="application/json"/>
<logger message="JSON Payload is #[payload]" level="INFO" doc:name="Logger"/>
<http:request config-ref="HTTP_Request_Configuration" path="/muleCWG" method="POST" doc:name="HTTP">
<http:request-builder>
<http:header headerName="access_token" value="U9P4CjhCsadIQzfJi13dHYdQLCfhmAi9OxYM8d7c"/>
</http:request-builder>
<http:success-status-code-validator values="200"/>
</http:request>
<byte-array-to-string-transformer doc:name="Byte Array to String"/>
<logger message="webservice response #[payload]" level="INFO" doc:name="Logger"/>
</flow>
</mule>
Please advice.
-Paresh (kendreparesh#gmail.com)
You can either use Bulk Update with mule bulk mode = "true" with parameterized query or Batch processing. But in your case bulk update will be helpful. No need to use for-each scope it will reduce the performance.
It doesn,t matter what is the count of records Bulk update can works on thousands of records. You can try something like following
<flow name="testdbFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/test" doc:name="HTTP"/>
<set-payload value="{"1234567890123456":"Y","1234567890123457":"Y"}" mimeType="application/json" doc:name="Set Payload"/>
<dw:transform-message doc:name="Transform Message">
<dw:input-payload />
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
(payload mapObject {
x: {
key : $$,
value : $
}
}).*x]]>
</dw:set-payload>
</dw:transform-message>
<json:json-to-object-transformer returnClass="java.util.List" doc:name="JSON to Object"/>
<db:update config-ref="MySQL_Configuration" bulkMode="true" doc:name="Database">
<db:dynamic-query><![CDATA[UPDATE cwg_ws_data SET SyncFlag = '#[payload.value]' WHERE IMEI = '#[payload.key]']]></db:dynamic-query>
</db:update>
</flow>
I have tested this with same input and its working fine. FYI dataweave is used for converting json to meaningful and accessible payload.
Hope this helps.

Datamapper and Salesforce Connector in mule

Im trying to map data from database to salesforce in mule is using CreateBulk option in Salesforce Connector
-->
<flow name="datamapperFlow1" doc:name="datamapperFlow1">
<poll doc:name="Poll">
<fixed-frequency-scheduler frequency="30" timeUnit="SECONDS"/>
<db:select config-ref="Generic_Database_Configuration" doc:name="Database">
<db:parameterized-query><![CDATA[select * from Persons1]]></db:parameterized-query>
</db:select>
</poll>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
<foreach doc:name="For Each">
<data-mapper:transform config-ref="Map_To_HRISASI__c" doc:name="Map To HRISASI__c"/>
</foreach>
<sfdc:create-bulk config-ref="Salesforce" type="HRISASI__c" doc:name="Salesforce">
<sfdc:objects ref="#[payload]"/>
</sfdc:create-bulk>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>
A batch job is created but records are failed to insert with the below error in sales force
<result>
<errors>
<fields>PHONE</fields>
<fields>EMPNAME</fields>
<fields>EMPLOYEEID</fields>
<message>
HRISASI__c: bad field names on insert/update call: PHONE, EMPNAME, EMPLOYEEID
</message>
<statusCode>INVALID_FIELD_FOR_INSERT_UPDATE</statusCode>
</errors>
<success>false</success>
<created>false</created>
</result>
my Data Mapper script looks like the below
//MEL
//START -> DO NOT REMOVE
output.__id = input.__id;
//END -> DO NOT REMOVE
output.EmployeeId__c = input.EmpId;
output.EmpName__c = input.Empname;
output.Phone__c = input.Phone;
Could someone please tell me what is the reason for the error
Thankyou in advance
The problem was because of using the datamapper inside the for each.
Payload outside the foreach doesn't contains the mapping and hence error was thrown when trying to map the data to salesforce

Unable to create dynamic file inbound endpoint in mule

I get a file path as an input to mule inside xml. Using XPATH expression, I am able to extract the path. I want to read a particular file from that path. I tried to define file inbound endpoint as below. But it doesn't seem to be working.
<flow name="flow1">
....
....
<set-session-variable variableName="filePath" value="#[xpath://filePath]" />
<flow-ref name="fileFlow"/>
</flow>
<flow name="fileFlow">
<file:inbound-endpoint path="#[header:SESSION:filePath]" />
</flow>
My understanding here is that no code can be placed before an inbound-endpoint. Hence I defined it in another flow. Please suggest if there is a way to read the file from a specified path.
Unfortunately, you cannot programmatically call an inbound-endpoint like that.
However the same functionality can be achieved using the Mule requester module:
Example:
<flow name="RequestFile" doc:name="RequestFile">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="requestfile" doc:name="HTTP"/>
<mulerequester:request config-ref="Mule_Requester" resource="file:///s/tmp/demorequester/read/#[message.inboundProperties['filename']]" returnClass="java.lang.String" doc:name="Request a file"/>
</flow>
Instructions here: https://github.com/mulesoft/mule-module-requester and https://blogs.mulesoft.com/dev/mule-dev/introducing-the-mule-requester-module/

Resources