I want to select records from a database and use them across different flows in mule.
My approach is to get the records using a Spring bean and pass it to a hashmap then return the hashmap and save it in a session variable.
Currently getting this error:
Message : Execution of the expression "message.payload.getServiceCodes()" failed. (org.mule.api.expression.ExpressionRuntimeException). Message payload is of type: HashMap
Code : MULE_ERROR--2
Its there a better approach? Or what I'm I doing wrong?
My Configuration XML
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:quartz="http://www.mulesoft.org/schema/mule/quartz" xmlns:jdbc-ee="http://www.mulesoft.org/schema/mule/ee/jdbc" xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml" xmlns:data-mapper="http://www.mulesoft.org/schema/mule/ee/data-mapper" xmlns:xm="http://www.mulesoft.org/schema/mule/xml" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:file="http://www.mulesoft.org/schema/mule/file" xmlns:jms="http://www.mulesoft.org/schema/mule/jms" 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.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/ee/jdbc http://www.mulesoft.org/schema/mule/ee/jdbc/current/mule-jdbc-ee.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.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/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/jms http://www.mulesoft.org/schema/mule/jms/current/mule-jms.xsd
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.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/data-mapper http://www.mulesoft.org/schema/mule/ee/data-mapper/current/mule-data-mapper.xsd
http://www.mulesoft.org/schema/mule/quartz http://www.mulesoft.org/schema/mule/quartz/current/mule-quartz.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd">
<jms:activemq-connector name="Active_MQ" brokerURL="tcp://localhost:61616" validateConnections="true" doc:name="Active MQ"></jms:activemq-connector>
<xm:jaxb-context name="myJaxb" doc:name="myJaxb" packageNames="com.test.jaxb"></xm:jaxb-context>
<spring:beans>
<spring:bean id="springDataSource" name="Bean" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<spring:property name="url" value="jdbc:mysql://localhost:3306/muledb"></spring:property>
<spring:property name="maxActive" value="30"></spring:property>
<spring:property name="removeAbandoned" value="true"></spring:property>
<spring:property name="driverClassName" value="com.mysql.jdbc.Driver"></spring:property>
<spring:property name="initialSize" value="20"></spring:property>
<spring:property name="username" value="root"></spring:property>
</spring:bean>
</spring:beans>
<quartz:connector name="quartzConnector" doc:name="Quartz">
<quartz:factory-property key="org.quartz.scheduler.instanceName" value="MuleScheduler1"></quartz:factory-property>
<quartz:factory-property key="org.quartz.threadPool.class" value="org.quartz.simpl.SimpleThreadPool"></quartz:factory-property>
<quartz:factory-property key="org.quartz.threadPool.threadCount" value="3"></quartz:factory-property>
<quartz:factory-property key="org.quartz.scheduler.rmi.proxy" value="false"></quartz:factory-property>
<quartz:factory-property key="org.quartz.scheduler.rmi.export" value="false"></quartz:factory-property>
<quartz:factory-property key="org.quartz.jobStore.class" value="org.quartz.simpl.RAMJobStore"></quartz:factory-property>
</quartz:connector>
<jdbc-ee:mysql-data-source name="MySQL_Data_Source" user="root" password="" url="jdbc:mysql://localhost:3306/muledb" transactionIsolation="UNSPECIFIED" doc:name="MySQL Data Source"></jdbc-ee:mysql-data-source>
<jdbc-ee:connector name="Database" dataSource-ref="MySQL_Data_Source" validateConnections="true" transactionPerMessage="false" queryTimeout="-1" pollingFrequency="0" doc:name="Database"></jdbc-ee:connector>
<!-- <flow name="JMSMessageFlow1" doc:name="JMSMessageFlow1" >
<jdbc-ee:inbound-endpoint queryKey="FirstUpdate" queryTimeout="-1" connector-ref="Database" doc:name="Database" pollingFrequency="0">
<jdbc-ee:query key="FirstUpdate" value="SELECT * FROM gcp_txn_log WHERE PROCESSED= 'Y'"></jdbc-ee:query>
<jdbc-ee:query key="FirstUpdate.ack" value="update gcp_txn_log set PROCESSED='N' where service_id = #[map-payload:service_id]"></jdbc-ee:query>
</jdbc-ee:inbound-endpoint>
<logger level="INFO" doc:name="Logger"/>
</flow> -->
<!-- <flow name="JMSMessageFlow2" doc:name="JMSMessageFlow2">
<jdbc-ee:inbound-endpoint queryKey="SelectAll" queryTimeout="-1" connector-ref="Database" doc:name="Database" pollingFrequency="0">
<jdbc-ee:transaction action="ALWAYS_BEGIN"></jdbc-ee:transaction>
<jdbc-ee:query key="SelectAll" value="SELECT * FROM gcp_txn_log WHERE PROCESSED= 'N'"></jdbc-ee:query>
<jdbc-ee:query key="SelectAll.ack" value="update gcp_txn_log set PROCESSED='Y' where service_id = #[map-payload:service_id] "></jdbc-ee:query>
</jdbc-ee:inbound-endpoint>
<xm:object-to-xml-transformer doc:name="Object to XML"></xm:object-to-xml-transformer>
<file:outbound-endpoint path="C:\Users\FASYL\Downloads" outputPattern="test#[function:datestamp:dd-MM-yy]_#[function:systime].xml" responseTimeout="10000" doc:name="File"></file:outbound-endpoint>
<jdbc-ee:outbound-endpoint queryKey="FirstUpdate" queryTimeout="-1" connector-ref="Database" doc:name="Database">
<jdbc-ee:query key="FirstUpdate" value="update gcp_txn_log set PROCESSED = 'N' WHERE PROCESSED = 'Y'"></jdbc-ee:query>
</jdbc-ee:outbound-endpoint>
</flow> -->
<flow name="JMSMessageFlow3" doc:name="JMSMessageFlow3">
<quartz:inbound-endpoint jobName="job2" repeatInterval="1" repeatCount="0" responseTimeout="10000" doc:name="Quartz" connector-ref="quartzConnector">
<quartz:event-generator-job>
<quartz:payload>Setting Session Variable</quartz:payload>
</quartz:event-generator-job>
</quartz:inbound-endpoint>
<component class="com.test.SchedulerComponent" doc:name="Java"></component>
<component doc:name="Java">
<singleton-object class="com.test.ServiceDAO">
<property key="dataSource" value-ref="springDataSource" value="null"/>
</singleton-object>
</component>
<message-properties-transformer scope="session" doc:name="Message Properties">
<add-message-property key="serviceDAO" value="#[message.payload]"/>
</message-properties-transformer>
<logger level="INFO" doc:name="Logger" message="#[sessionVars['serviceDAO']['1001']]"/>
</flow>
<!-- <flow name="JMSMessageFlow1" doc:name="JMSMessageFlow1">
</flow> -->
<flow name="JMSMessageFlow4" doc:name="JMSMessageFlow4">
<jms:inbound-endpoint queue="StudioIns" connector-ref="Active_MQ" doc:name="JMS"/>
<xm:jaxb-xml-to-object-transformer jaxbContext-ref="myJaxb" returnClass="com.test.jaxb.MsgContent"></xm:jaxb-xml-to-object-transformer>
<choice doc:name="Choice">
<when expression="payload.getMsgBody().getValue() == 'fundstransfer'" >
<pooled-component doc:name="Java">
<prototype-object class="com.test.PersonComponent">
<property key="dataSource" value-ref="springDataSource" value="null"/>
</prototype-object>
</pooled-component>
</when>
<when expression="#[sessionVars['serviceDAO']['1001'] == 1] ">
<pooled-component doc:name="Java">
<prototype-object class="com.test.SecondPersonComponent">
<property key="dataSource" value-ref="springDataSource" value="null"/>
</prototype-object>
</pooled-component>
</when>
</choice>
<logger message="#[sessionVars['serviceDAO']]" level="INFO" doc:name="Logger"/>
<file:outbound-endpoint path="D:\Documents\MuleStudio\workspace\jms_amq\bin\com\test" outputPattern="new.txt" responseTimeout="10000" doc:name="File"/>
</flow>
</mule>
The error indicates your payload is a HashMap: "Message payload is of type: HashMap". So the expression: message.payload.getServiceCodes() won't work as a HashMap doesn't have a method named 'getServiceCodes()'. If you want access elements of that HashMap you can use MEL(Mule Expression Language - http://www.mulesoft.org/documentation/display/current/Mule+Expression+Language+MEL) in a few ways.
Either via standard java method invocation such as:
payload.get('mykey')
or you can use MEL short hand such as:
payload['mykey'] or payload.mykey
Ont he other point about session variables you can store it in a session variable via the "set-session-variable" message processor and access the elements in a similar way. You can refer to it using "sessionVars" instead of "payload" and this time it will be a map of maps so:
sessionVars.mymap.mykey or sessionVars['mymap']['mykey'] etc.
Related
I have one application which is Mule 3, now I need to migrate it into Mule 4.
I implemented and changed some code but it through exceptions that tag not supported i.e 'rest-router' is not supported.
<rest-router:router templateUri="${igate.url}">
<!--Migration ERROR: The migration of 'rest-router' is not supported.-->
<!-- For more information refer to:-->
<!-- * https://docs.mulesoft.com/mule-runtime/4.1/migration-connectors>--
<!-- * https://beta.docs.stgx.mulesoft.com/beta-mule-migration-tool/mule-runtime/4.1/migration-tool.html#unsupported_connectors-->
<rest-router:post>
<ee:transform xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core" doc:name="JSON to Object">
<ee:message>
<ee:set-payload>%dw 2.0 output application/java --- payload as Object { class: 'com.ifi.igate.model.Transaction'}</ee:set-payload>
</ee:message>
</ee:transform>
<flow-ref name="igate-object-flow" doc:name="igate-object-flow" />
<ee:transform xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core" doc:name="Object to JSON" mimeType="application/json">
<ee:message>
<ee:set-payload>%dw 2.0 output application/json --- payload</ee:set-payload>
</ee:message>
</ee:transform>
</rest-router:post>
</rest-router:router>
Full XML file in Mule 3 which we need to migrate on Mule 4 -
<spring:beans>
<spring:bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<spring:property name="ignoreUnresolvablePlaceholders" value="true"/>
<spring:property name="location" value="igate.properties"/>
</spring:bean>
<spring:bean id="validation" class="com.ifi.igate.integration.iclient.ValidationTransformer">
<spring:property name="transactionTypes">
<spring:list>
<spring:value>INQ-REQ</spring:value>
<spring:value>DEP-REQ</spring:value>
<spring:value>WIT-REQ</spring:value>
</spring:list>
</spring:property>
</spring:bean>
<spring:bean id="iGateStub" class="com.ifi.igate.stub.IGateStub">
<spring:property name="handlers">
<spring:map>
<spring:entry key="INQ-REQ">
<spring:bean class="com.ifi.igate.stub.handlers.InqHandler"/>
</spring:entry>
<spring:entry key="WIT-REQ">
<spring:bean class="com.ifi.igate.stub.handlers.WitHandler"/>
</spring:entry>
<spring:entry key="DEP-REQ">
<spring:bean class="com.ifi.igate.stub.handlers.DepHandler"/>
</spring:entry>
</spring:map>
</spring:property>
</spring:bean>
</spring:beans>
<rest-router:config/>
<http:connector name="httpConnector" doc:name="HTTP\HTTPS">
<receiver-threading-profile maxThreadsActive="10" />
</http:connector>
<flow name="igate-json-flow" doc:name="igate-json-flow">
<http:inbound-endpoint exchange-pattern="request-response" host="${igate.host}" port="${igate.port}" doc:name="HTTP"/>
<rest-router:router templateUri="${igate.url}">
<rest-router:post>
<json:json-to-object-transformer xmlns:json="http://www.mulesoft.org/schema/mule/json" returnClass="com.ifi.igate.model.Transaction" doc:name="JSON to Object"></json:json-to-object-transformer>
<flow-ref name="igate-object-flow" doc:name="igate-object-flow"/>
<json:object-to-json-transformer xmlns:json="http://www.mulesoft.org/schema/mule/json" doc:name="Object to JSON" mimeType="application/json"></json:object-to-json-transformer>
</rest-router:post>
</rest-router:router>
<rest-router:router templateUri="${igate-stub.url}">
<rest-router:post>
<json:json-to-object-transformer xmlns:json="http://www.mulesoft.org/schema/mule/json" returnClass="com.ifi.igate.model.Transaction" doc:name="JSON to Object"/>
<component doc:name="IGateStub">
<spring-object bean="iGateStub"/>
</component>
<json:object-to-json-transformer xmlns:json="http://www.mulesoft.org/schema/mule/json" doc:name="Object to JSON" mimeType="application/json"/>
</rest-router:post>
</rest-router:router>
</flow>
<sub-flow name="igate-object-flow" doc:name="igate-object-flow">
<transformer ref="validation"/>
<choice>
<when expression="#[message.payload.trxstatus == 0]">
<logger message="#[message.payload.trxreason]" level="ERROR" doc:name="Logger"/>
</when>
<otherwise>
<set-variable variableName="request" value="#[message.payload]" doc:name="save request"/>
<flow-ref name="promotions-flow" doc:name="Promotions Flow"/>
<flow-ref name="ifi-membership-flow" doc:name="Accumulate Spending"/>
<!-- logger message="Before backend" level="ERROR" doc:name="Logger"/-->
<flow-ref name="rewards-flow" doc:name="Rewards Flow"/>
<choice>
<when expression="#[message.payload.values['PTS']>0 || message.payload.trxtype=='INQ-REQ']">
<flow-ref name="${igate.membership}-membership-flow" doc:name="External Membership Flow"/>
</when>
<otherwise>
<vm:outbound-endpoint exchange-pattern="request-response" path="membership/ifi" />
</otherwise>
</choice>
<!-- logger message="After backend" level="ERROR" doc:name="Logger"/-->
<flow-ref name="promotions-flow" doc:name="Promotions Flow"/>
<flow-ref name="rewards-flow" doc:name="Rewards Flow"/>
<flow-ref name="ifi-membership-flow" doc:name="Manage balances"/>
<flow-ref name="pricing-flow" doc:name="Pricing Flow"/>
</otherwise>
</choice>
</sub-flow>
</mule>
'rest-router' is not supported in Mule 4 only need replacement for that tag or How I can migrate it into Mule 4.
rest-router seems to be an unsupported and unmaintained (last commit is from 2012) module for Mule 3. You best bet is to migrate from scratch and use APIKit instead. You will need to write a RAML specification for your API and Studio will create all the needed scaffolding from it.
I have a JSON message say
{"menu": {
"id": "file",
"value": "File",
"popup": {
"menuitem": [
{"value": "New", "onclick": "CreateNewDoc()"},
{"value": "Open", "onclick": "OpenDoc()"},
{"value": "Close", "onclick": "CloseDoc()"}
]
}
}}
I would want to encrypt on the Id field in the JSON like below.
{"menu": {
"id": "98jshr0837#",
"value": "File",
"popup": {
"menuitem": [
{"value": "New", "onclick": "CreateNewDoc()"},
{"value": "Open", "onclick": "OpenDoc()"},
{"value": "Close", "onclick": "CloseDoc()"}
]
}
}}
I use the below code for encryption:
<flow name="hf-eai-crm-plan-search-detail-api-flow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<byte-array-to-string-transformer doc:name="Byte Array to String"/>
<json:object-to-json-transformer doc:name="Object to JSON"/>
<logger message="#[message.payload.menu.id]" level="INFO" doc:name="Logger"/>
<encryption:decrypt config-ref="Encryption" doc:name="Encryption"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>
Let me know how this can be achieved?
I have modified your flow a bit and able to get encrypted value of a single element as follows :-
<flow name="hf-eai-crm-plan-search-detail-api-flow" doc:name="hf-eai-crm-plan-search-detail-api-flow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<object-to-string-transformer doc:name="Object to String"/>
<json:json-to-object-transformer returnClass="java.util.HashMap" doc:name="JSON to Object"/>
<logger message="before encryption #[message.payload.menu.id]" level="INFO" doc:name="Logger"/>
<encryption:encrypt config-ref="Encryption" doc:name="Encryption" using="JCE_ENCRYPTER" input-ref="#[message.payload.menu.id]"/>
<logger message="After encryption #[message.payload]" level="INFO" doc:name="Logger"/>
<encryption:decrypt config-ref="Encryption" using="JCE_ENCRYPTER" doc:name="Decrypt the xml payload" />
<logger message="Element After Decryption :- #[message.payload]" level="INFO" category="NormalEncryption" doc:name="Logger"/>
</flow>
You can see in the below screenshots for your reference :-
I have also decrypted to show you the value of element
EDITED Solution
Well, there is an attribute xpath in <encryption/> which can be used to encrypt an element in XML. But unfortunately, I didn't find anything for JSON that can parse it and encrypt an element from it... So I created the following 2 solutions for you :-
Solution1:-
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<encryption:config name="Encryption" enableLanguage="true" doc:name="Encryption">
<encryption:jce-encrypter-config algorithm="CAST5" key="poso123456789lal" />
</encryption:config>
<flow name="hf-eai-crm-plan-search-detail-api-flow" >
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<object-to-string-transformer doc:name="Object to String"/>
<json:json-to-object-transformer returnClass="java.util.HashMap" doc:name="JSON to Object"/>
<set-variable doc:name="Variable" value="#[message.payload.menu.value]" variableName="value"/>
<set-variable doc:name="Variable" value="#[message.payload.menu.popup]" variableName="popup"/>
<logger message="before encryption #[message.payload.menu.id]" level="INFO" doc:name="Logger"/>
<encryption:encrypt config-ref="Encryption" doc:name="Encryption" using="JCE_ENCRYPTER" input-ref="#[message.payload.menu.id]"/>
<set-variable doc:name="Variable" value="#[message.payload]" variableName="id"/>
<logger message="Encryption #[message.payload]" level="INFO" doc:name="Logger"/>
<expression-transformer
expression="#[[
'menu':[
'id': flowVars.id,
'value': flowVars.value,
'popup': flowVars.popup
]
]
]" doc:name="Expression"/>
<json:object-to-json-transformer doc:name="Object to JSON"/>
<logger message="After encryption #['\n' + message.payload]" level="INFO" doc:name="Logger"/>
</flow>
Here you can see I have parsed the JSON payload and saved each element value in variables, and then using the variables I am able to construct the JSON you required dynamically using Expression Transformer and also included the encrypted element in it.
Alternate Solution :-
<flow name="hf-eai-crm-plan-search-detail-api-flow" >
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<object-to-string-transformer doc:name="Object to String"/>
<json:json-to-object-transformer returnClass="java.util.HashMap" doc:name="JSON to Object"/>
<set-variable doc:name="Variable" value="#[message.payload]" variableName="myPayload"/>
<logger message="before encryption #[message.payload.menu.id]" level="INFO" doc:name="Logger"/>
<set-variable doc:name="Variable" value="#[message.payload]" variableName="id"/>
<encryption:encrypt config-ref="Encryption" doc:name="Encryption" using="JCE_ENCRYPTER" input-ref="#[message.payload.menu.id]"/>
<logger message="Encryption #[message.payload] " level="INFO" doc:name="Logger"/>
<expression-transformer expression="#[flowVars.myPayload.menu.id=message.payload;flowVars.myPayload]" />
<json:object-to-json-transformer doc:name="Object to JSON"/>
<json:object-to-json-transformer doc:name="Object to JSON"/>
</flow>
Here you can see, using Expression transformer, I am able to update only the element I required to encrypt
So using any of the above solution you will get to encrypt the element you require in the JSON as below :-
Hope this help :)
To keep the payload we can utilize Message Enricher. Please refer to the following configuration, it might meet your purpose:
<flow name="hf-eai-crm-plan-search-detail-api-flow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/encrypt" doc:name="HTTP" allowedMethods="POST" />
<json:json-to-object-transformer returnClass="java.util.Map" doc:name="JSON to Object" />
<logger message="The JSON before encryption: #[payload]" level="INFO" doc:name="Logger - initial" />
<enricher source="#[payload]" target="#[payload.menu.id]" doc:name="Message Enricher">
<encryption:encrypt config-ref="Encryption" input-ref="#[message.payload.menu.id]" using="JCE_ENCRYPTER" doc:name="Encryption"/>
</enricher>
<logger message="The JSON after encryption: #[payload]" level="INFO" doc:name="Logger - id encrypted" />
<enricher source="#[payload]" target="#[payload.menu.id]" doc:name="Message Enricher">
<encryption:decrypt config-ref="Encryption" input-ref="#[payload.menu.id]" using="JCE_ENCRYPTER" doc:name="Decryption"/>
</enricher>
<logger message="The JSON after decryption: #[payload]" level="INFO" doc:name="Logger - decrypted (back to original)" />
</flow>
The result of this configuration is:
Without JSON to Object transformer, just modifying your configuration and add a little bit tricky String manipulation:
<flow name="hf-eai-crm-plan-search-detail-api-flow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/encrypt" doc:name="HTTP" allowedMethods="POST" />
<byte-array-to-string-transformer doc:name="Byte Array to String"/>
<json:object-to-json-transformer doc:name="Object to JSON"/>
<logger message="The JSON before encryption: #[payload]" level="INFO" doc:name="Logger - initial" />
<set-variable variableName="jsonOriginal" value="#[payload]" doc:name="Keep the original JSON"/>
<set-payload value="#[json:menu]" doc:name="Set Payload with JSON menu"/>
<set-variable variableName="idValue" value="#[json:id]" doc:name="Get value of id"/>
<encryption:encrypt config-ref="Encryption" input-ref="#[flowVars.idValue]" using="JCE_ENCRYPTER" doc:name="Encryption"/>
<logger message="The id after encryption: #[payload]" level="INFO" doc:name="Logger - id encrypted" />
<set-payload value="#[flowVars.jsonOriginal.replaceAll("\"id\": \"" + flowVars.idValue + "\"", "\"id\": \"" + payload + "\"")]" doc:name="Set Payload"/>
<logger message="The JSON after encryption: #[payload]" level="INFO" doc:name="Final JSON" />
</flow>
Following is the result:
I have a Mule flow which uses HTTP Request endpoint in Mule CE3.6.1. It needs to use encoded HTTP url to get the correct data.
Please note the encoded url: /items?q=%2Blabel%3ABOTV2309H*%20%2Bparent.uri%3A%5C%2Fbristol%5C%2Ftest%5C%2Fgateway%5C%2F*&rows=100&start=0
Here is the test flow.
<?xml version="1.0" encoding="UTF-8"?>
<mule 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="CE-3.6.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/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd">
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8089" basePath="/" usePersistentConnections="false" doc:name="HTTP Listener Configuration"/>
<http:request-config name="HTTP_Request_Config_Search" host="testserver" port="80" basePath="/index" usePersistentConnections="false" doc:name="HTTP Request Configuration"/>
<flow name="testFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="*" allowedMethods="POST" doc:name="HTTP"/>
<object-to-string-transformer doc:name="Object to String"/>
<logger level="INFO" doc:name="Logger"/>
<http:request config-ref="HTTP_Request_Config_Search" path="/items?q=%2Blabel%3ABOTV2309H*%20%2Bparent.uri%3A%5C%2Fbristol%5C%2Ftest%5C%2Fgateway%5C%2F*&rows=100&start=0" method="GET" doc:name="HTTP"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>
</mule>
When the Mule flow runs, here is the url being requested (Found through wireshark):
/items?q=%20label%3ABOTV2309H%2A%20%20parent.uri%3A%5C%2Fbristol%5C%2Ftest%5C%2Fgateway%5C%2F%2A&rows=100&start=0
Please note %2B is replaced with %20 in two places, which obviously do not return the data I need.
Is this an issue with HTTP endpoint?
Thanks!
I divided the params into query and uri params. Then this issue got resolved.
<http:request config-ref="HTTP_Request_Config_Search" path="/items" method="GET" doc:name="HTTP">
<http:request-builder>
<http:query-param paramName="q" value="+label:BOTV2309H* +parent.uri:\/test\/gateway\/*"/>
<http:uri-param paramName="rows" value="100"/>
<http:uri-param paramName="start" value="0"/>
</http:request-builder>
</http:request>
I have the following flow :
<flow name="SOAPWebService" doc:name="SOAPWebService">
<http:inbound-endpoint address="http://localhost:8088/esb/" exchange-pattern="request-response" doc:name="HTTP">
</http:inbound-endpoint>
<choice doc:name="Choice">
<when expression="#[payload.contains('c22')]">
<set-variable variableName="paramCtr" value="#[message.inboundProperties['ctr']]" doc:name="conteneur"/>
<set-variable variableName="paramC" value="#[message.inboundProperties['c']]" doc:name="critere"/>
<component class="com.example.components.SampleComponent" doc:name="Java"/>
<mulexml:xslt-transformer maxIdleTransformers="2" maxActiveTransformers="5" xsl-file="C:\MuleStudio\SandBox\resources\PrepareRequestXMLPort.xsl" doc:name="XSLT">
<mulexml:context-property key="paramCtr" value="#[flowVars['paramCtr']]"/>
<mulexml:context-property key="paramC" value="#[flowVars['paramC']]"/>
</mulexml:xslt-transformer>
<cxf:proxy-client payload="body" enableMuleSoapHeaders="true" doc:name="SOAP"/>
<http:outbound-endpoint exchange-pattern="request-response" address="http://localhost:8080/ClientsDB/port" doc:name="PortWS"/>
</when>
<otherwise>
<set-variable variableName="paramCtr" value="#[message.inboundProperties['ctr']]" doc:name="conteneur"/>
<set-variable variableName="paramC" value="#[message.inboundProperties['c']]" doc:name="critere"/>
<component class="com.example.components.SampleComponent" doc:name="Java"/>
<mulexml:xslt-transformer maxIdleTransformers="2" maxActiveTransformers="5" xsl-file="C:\MuleStudio\SandBox\resources\PrepareRequestXMLDouane.xsl" doc:name="XSLT">
<mulexml:context-property key="paramCtr" value="#[flowVars['paramCtr']]"/>
<mulexml:context-property key="paramC" value="#[flowVars['paramC']]"/>
</mulexml:xslt-transformer>
<cxf:proxy-client payload="body" enableMuleSoapHeaders="true" doc:name="SOAP"/>
<http:outbound-endpoint exchange-pattern="request-response" address="http://localhost:8080/ClientsDB/douane" doc:name="DouaneWS"/>
</otherwise>
</choice>
<byte-array-to-string-transformer doc:name="Byte Array to String" />
<file:outbound-endpoint path="C:\MuleStudio\SandBox\output" outputPattern="#[function:datestamp:dd-MM-yy]_#[function:systime].xml " responseTimeout="10000" doc:name="Outgoing File"/>
I want to test if an http request like http://localhost:8088/esb/?type=xxxx&id=1234 if it contains the String xxxx in a way to route the request to the desired web service proxy.
I've tried withe the expression expression="#[string.contains['xxxxx']]" but it does not seem to work.
any idea?
thank you.
Two things: You will need to replace "string" with the property you want to execute on. Either a message property or payload etc. i.e #[payload.contains...].
"contains" is a Java method on java.lang.String so you need to use standard Java method invocation with () instead of [].
Working example:
<choice doc:name="Choice">
<when expression="#[payload.contains('xxxx')]">
<logger level="ERROR" message="YES" />
</when>
<otherwise>
<logger level="ERROR" message="NO" />
</otherwise>
</choice>
Or directly work off inbound properties for your query params:
After your http inbound use set-variable to store your query params into flow variables.
And then use the flow variales in your expression.
<set-variable value="#[message.inboundProperties['id']]" variableName="paramId"></set-variable>
<set-variable value="#[message.inboundProperties['type']]" variableName="paramType"></set-variable>
or you can directly use inbound property for comparision.
<when expression="#[message.inboundProperties['type']== 'XXXX']">
When I run my flow, I get the following error `
<org.apache.cxf.staxutils.DepthXMLStreamReader>
<reader class="org.mule.module.cxf.support.StreamClosingInterceptor$1">
<reader class="com.ctc.wstx.sr.ValidatingStreamReader">
<mXml11>false</mXml11>
<mInputBuffer>xmlns:ns2="http://wsdouane/"><return><douanePK><idConteneurId>ctr1</idConteneurId><idCritereId>C11</idCritereId></douanePK><valeurId>oui</valeurId></return></ns2:findResponse></S:Body></S:Envelope>.................
we can see the correct soap response starting from the <mInputBuffer>, is there a way to get only the soap response??
here is my flow
<flow name="SOAPWebService" doc:name="SOAPWebService">
<http:inbound-endpoint exchange-pattern="request-response" address="http://localhost:8088/esb" doc:name="HTTP"/>
<object-to-string-transformer doc:name="Object to String"/>
<choice doc:name="Choice">
<when expression="#[payload.contains('C22')]">
<set-variable variableName="paramCtr" value="#[message.inboundProperties['ctr']]" doc:name="conteneur"/>
<set-variable variableName="paramC" value="#[message.inboundProperties['c']]" doc:name="critere"/>
<component class="com.example.components.SampleComponent" doc:name="Java"/>
<mulexml:xslt-transformer maxIdleTransformers="2" maxActiveTransformers="5" xsl-file="C:\MuleStudio\SandBox\resources\PrepareRequestXMLPort.xsl" doc:name="XSLT">
<mulexml:context-property key="paramCtr" value="#[flowVars['paramCtr']]" />
<mulexml:context-property key="paramC" value="#[flowVars['paramC']]" />
</mulexml:xslt-transformer>
<cxf:proxy-client payload="body" enableMuleSoapHeaders="true" doc:name="SOAP"/>
<http:outbound-endpoint exchange-pattern="request-response" address="http://localhost:8080/ClientsDB/port" doc:name="PortWS"/>
<byte-array-to-string-transformer doc:name="Byte Array to String" />
</when>
<otherwise>
<set-variable variableName="paramCtr" value="#[message.inboundProperties['ctr']]" doc:name="conteneur"/>
<set-variable variableName="paramC" value="#[message.inboundProperties['c']]" doc:name="critere"/>
<component class="com.example.components.SampleComponent" doc:name="Java"/>
<mulexml:xslt-transformer maxIdleTransformers="2" maxActiveTransformers="5" xsl-file="C:\MuleStudio\SandBox\resources\PrepareRequestXMLDouane.xsl" doc:name="XSLT">
<mulexml:context-property key="paramCtr" value="#[flowVars['paramCtr']]" />
<mulexml:context-property key="paramC" value="#[flowVars['paramC']]" />
</mulexml:xslt-transformer>
<cxf:proxy-client payload="body" enableMuleSoapHeaders="true" doc:name="SOAP"/>
<http:outbound-endpoint exchange-pattern="request-response" address="http://localhost:8080/ClientsDB/douane" doc:name="DouaneWS"/>
<byte-array-to-string-transformer doc:name="Byte Array to String"/>
</otherwise>
</choice>
<xm:object-to-xml-transformer doc:name="Object to XML"/>
<file:outbound-endpoint path="C:\MuleStudio\SandBox\output" outputPattern="#[function:datestamp:dd-MM-yy]_#[function:systime].xml " responseTimeout="10000" doc:name="Outgoing File"/>
</flow>
thank you.
This expression #[payload.contains('c22')] can't work because the payload is an InputStream. Aren't you seeing stack traces in Mule's logs?
In any case, try adding <object-to-string-transformer /> before the choice and see if it fixes the issue.
EDIT:
The problem is that you're using XStream (in xm:object-to-xml-transformer) to serialize the CXF response object (org.apache.cxf.staxutils.DepthXMLStreamReader) into XML. The CXF response should not be messed with and should be handled by the cxf:proxy-client in the response phase of the flow. The xm:object-to-xml-transformer and file:outbound-endpoint after the choice router are probably disturbing this mechanism. Try to wrap them in a response element above the choice router to they execute after it in the response phase.
Note that I have already given you this advice in your other question https://stackoverflow.com/a/16615537/387927 but you did not react to it.
Also I don't think byte-array-to-string-transformer does anything: the message payload after the http:outbound-endpoints should be org.apache.cxf.staxutils.DepthXMLStreamReader, preventing this transformer to fire.