I have this xml file
<Collections xmlns:foo="http://www.foo.org/" xmlns:bar="http://www.bar.org">
<Collection value="bob">
<Environments>
<Environment>amazon</Environment>
</Environments>
<ContentTypes>
<Type>Standard:ShowVideo</Type>
<Type>Standard:VideoPlaylist</Type>
<Type>Blog</Type>
</ContentTypes>
</Collection>
<Collection value="sandy">
<Environments>
<Environment>amazon</Environment>
</Environments>
<ContentTypes>
<Type>Blog</Type>
</ContentTypes>
</Collection>
and am executing this xpath query in my Mule flow. It uses 2 flowVars 'environment' and 'contentType' which come from a Redis message.
<set-variable variableName="collectionQuery" value="/Collections/Collection[Environments/Environment='#[environment]' and ContentTypes/Type='#[contentType]']/#value" />
<logger message="collectionQuery is #[collectionQuery]" level="INFO" />
<set-payload value="#[xpath(collectionQuery)]" />
<logger message="payload is #[payload]" level="INFO" />
Here you can see the fully instantiated query and the result.
INFO] org.mule.api.processor.LoggerMessageProcessor: collectionQuery is /Collections/Collection[Environments/Environment='amazon' and ContentTypes/Type='Blog']/#value
INFO] org.mule.api.processor.LoggerMessageProcessor: payload is [org.dom4j.tree.DefaultAttribute#140207e0 [Attribute: name value value "bob"], org.dom4j.tree.DefaultAttribute#11530d63 [Attribute: name value value "sandy"]]
The result is what looks like an array of 2 org.dom4j.tree objects. I just need an ArrayList of attribute 'value' such as this
[bob,sandy]
I can do this in Groovy but not using Mule's xpath functionality.
only this worked for me
<set-variable variableName="collectionName" value="#[payload.getText()]" doc:name="collectionName"/>
<logger message="now processing #[collectionName]" level="INFO" doc:name="Logger"/>
My xpath expression returned an array of DefaultAttribute. To get the actual value of the attribute, as a String, I needed to call the getValue() method with my foreach loop.
<foreach doc:name="For Each">
<set-variable variableName="collectionName" value="#[payload.getValue()]" doc:name="collectionName"/>
<logger message="now processing #[collectionName]" level="INFO" doc:name="Logger"/>
</foreach>
output:
INFO] org.mule.api.processor.LoggerMessageProcessor: now processing bob
INFO] org.mule.api.processor.LoggerMessageProcessor: now processing sandy
Related
I have an async flow with JSON payload (Payload Type as java.lang.String) and trying to do a POST to HTTP Request Connector but I am getting a 400 error. When I run the app in debugger, the payload type changes to org.glassfish.grizzly.utils.BufferInputStream from JSON string which I believe is the issue.
How do I resolve this issue?
Thanks
If you use a Dataweave transformer, using JAVA output returns that Object of type "org.glassfish.grizzly.utils.BufferInputStream", e.g:
%dw 1.0
%output application/java
---
payload
Try adding the Object to JSON after your Dataweave transformation!
<object-to-string-transformer doc:name="Object to String"/>
<flow name="createFlow">
<vm:inbound-endpoint exchange-pattern="one-way" path="createApi" connector-ref="VMConfiguration" doc:name="VM"/>
<enricher doc:name="Message Enricher" source="payload" target="#[flowVars.createApiPayload]">
<flow-ref name="createBomCollection" doc:name="createBomCollection"/>
</enricher>
<logger message="Payload after Create Api Call: #[message.payloadAs(java.lang.String)]" level="INFO" doc:name="Logger"/>
<set-payload value="#[message.payload]" mimeType="application/json" doc:name="Set Payload"/>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
{
(createApi: payload.createApi) when (payload.createApi != null)
}]]></dw:set-payload>
</dw:transform-message>
</flow>
<sub-flow name="createApiCollection">
<set-session-variable variableName="retryCount" value="#[new java.util.concurrent.atomic.AtomicInteger(0)]" doc:name="initialize retryCount"/>
<logger message="Payload before system Post: #[message.payload]" level="INFO" doc:name="Logger"/>
<http:request config-ref="System_HTTP_Request_Configuration" path="/bom1" method="POST" doc:name="HTTP">
<http:request-builder>
<http:header headerName="Content-Type" value="application/json"/>
<http:header headerName="requestID" value="#[sessionVars.requestID]"/>
<http:header headerName="transactionID" value="#[sessionVars.transactionID]"/>
<http:header headerName="quoteID" value="#[sessionVars.quoteID]"/>
<http:header headerName="operationName" value="#[sessionVars.operationName]"/>
</http:request-builder>
</http:request>
</sub-flow>
I have below XML
<response>
<data-table filter="XXX" count="26">
<columns>
<column>sampm</column>
<column>sampn</column>
</columns>
<rows>
<row attr="535545">
<field>sampx</field>
<field>sampy</field>
</row>
<row attr="535548">
<field>samp1</field>
<field>samp2</field>
</row>
</rows>
</data-table>
</response>
From this response I have to loop over rows i.e; /response/data-table/rows/row
So here is my mule code snippet with for each
<http:request config-ref="HTTP_REQUEST" path="api/query" method="GET" doc:name="HTTP" followRedirects="true">
</http:request>
<object-to-string-transformer doc:name="Object to String"/>
<foreach collection="#[xpath3('//response/data-table/rows')]" doc:name="For Each">
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</foreach>
But I am getting a warning "The expression does not evaluate to a type that can be split: java.lang.String"
Is there any work around this problem
Rows would return you an object, try changing your expression to xpath3('//query-response/data-table/rows/row')
Specify the xpath3 return type to be a NODESET:
<foreach
collection="#[xpath3('//query-response/data-table/rows', payload, 'NODESET')]"
This should be iterable.
My cache block never works, always the http request is made for same values.
<ee:object-store-caching-strategy name="eventIdCachingStrategy" doc:name="Autobulk EventID Caching Strategy" keyGenerationExpression="#[flowVars['ablMapEventToListingParameters']]">
<managed-store storeName="${xyz.eventid.cache.store.name}" persistent="true" maxEntries="${xyz.eventid.cache.max.entries}" entryTTL="${xyz.eventid.cache.entry.timetolive}" expirationInterval="${xyz.eventid.cache.expiration.interval}" />
</ee:object-store-caching-strategy>
<sub-flow name="mapEventsForListings" doc:name="mapEventsForListings">
<logger message="Entering mapEventsForListings flow..." level="INFO" doc:name="Logger"/>
<set-variable variableName="mapEventsForListingsTimeInMillis" value="#[new java.util.Date().getTime()]" doc:name="Set Entry Time In Millis"/>
<foreach doc:name="Map Event ID to each listing">
<choice doc:name="Choice">
<when expression="#[payload.getEvent().getVenue().isEmpty() || payload.getEvent().getDate().isEmpty() || payload.getExternalListingId().isEmpty() || payload.getPricePerProduct().getAmount()==0]">
<logger message="Missing input data for Payload" level="INFO" doc:name="Listing Missing Data Fields"/>
<set-variable variableName="noOfIncompleteListings" value="#[noOfIncompleteListings + 1]" doc:name="Increment Incomplete Listings Error Count"/>
</when>
<otherwise>
<set-variable variableName="ablMapEventToListingParameters" value="/?locale=en_US&venueName=#[payload.getEvent().getVenue()]&eventDateLocal=#[payload.getEvent().getDate()]" doc:name="Autobulk Event Search Parameters"/>
<set-variable variableName="originalListingRequest" value="#[payload]" doc:name="Variable"/>
<set-payload value="#[null]" doc:name="Set Payload"/>
<ee:cache doc:name="Cache" cachingStrategy-ref="eventIdCachingStrategy">
<https:outbound-endpoint exchange-pattern="request-response" method="GET" connector-ref="HttpsClientConnector" address="${xyz.search.catalog.events.ship.api.url}#[flowVars['ablMapEventToListingParameters']]" contentType="application/json" doc:name="HTTP Outbound Call to BulkCreateListing API">
<message-properties-transformer scope="outbound">
<add-message-property key="TARGET_HOST" value="${target.host}"/>
<add-message-property key="Authorization" value="#[flowVars['shUserBearerToken']]"/>
<add-message-property key="Content-Type" value="application/json"/>
</message-properties-transformer>
</https:outbound-endpoint>
<echo-component doc:name="Echo"/>
</ee:cache>
</otherwise>
</choice>
</flow>
Value of flowVars['ablMapToListingParameters'] = www.api-dev.xyz.com/search/catalog/events/ship/v3/?locale=en_US&venueName=SAPCenter&eventDateLocal=2015-07-16T20:00
Try with the following config :-
<ee:object-store-caching-strategy name="cachingStrategy" doc:name="cachingStrategy">
<managed-store storeName="myNonPersistentManagedObjectStore" maxEntries="-1" entryTTL="20000" expirationInterval="5000"/>
</ee:object-store-caching-strategy>
Also, you are setting the payload null before your cache scope ... cache scope require the payload to determine if the response can be cached or not.
For same payload it will make a cache-hit and provide the response from cache else it will process the message and store it in cache
ref:- https://docs.mulesoft.com/mule-user-guide/v/3.7/cache-scope
I have two jms consumers, each in a different flow. I want to use another flow to aggregate the messages of thoe two messages. and also need to keep the correlation Ids as i need to split the payload and send back the messages.
<flow name="integration-consumer-client1" doc:name="integration-consumer-client1">
<jms:inbound-endpoint doc:name="JMS" connector-ref="Active_MQ" queue="client1.publish"/>
<logger message="Consumes Client One = #[payload]" level="INFO" doc:name="Logger"/>
<logger message="Client One Correlation = #[message.correlationId]" level="INFO" doc:name="Logger"/>
<vm:outbound-endpoint exchange-pattern="one-way" path="client1" doc:name="VM"/>
</flow>
<flow name="integration-consumer-client2" doc:name="integration-consumer-client2">
<jms:inbound-endpoint doc:name="JMS" connector-ref="Active_MQ" queue="client2.publish"/>
<logger message="Consumes Client Two = #[payload]" level="INFO" doc:name="Logger"/>
<logger message="Client Two Correlation = #[message.correlationId]" level="INFO" doc:name="Logger"/>
<vm:outbound-endpoint exchange-pattern="one-way" path="client2" doc:name="VM"/>
</flow>
<flow name="integration-internetsolutionsFlow1" doc:name="integration-internetsolutionsFlow1">
<scatter-gather doc:name="Scatter-Gather">
<vm:inbound-endpoint exchange-pattern="one-way" path="client1" doc:name="VM"/>
<vm:inbound-endpoint exchange-pattern="one-way" path="client2" doc:name="VM"/>
</scatter-gather>
</flow>
I tried to use the scatter gather with two inbound VMs but get the following error:
Caused by: org.xml.sax.SAXParseException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'vm:inbound-endpoint'. One of '{"http://www.mulesoft.org/schema/mule/core":annotations, "http://www.mulesoft.org/schema/mule/core":custom-aggregation-strategy, "http://www.mulesoft.org/schema/mule/core":threading-profile, "http://www.mulesoft.org/schema/mule/core":abstract-message-processor, "http://www.mulesoft.org/schema/mule/core":abstract-outbound-endpoint, "http://www.mulesoft.org/schema/mule/core":abstract-mixed-content-message-processor}' is expected.
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
The reason of the error is integration-internetsolutionsFlow1 doesn't have any inbound endpoint ..
What you can do is following :-
Use vm:outbound-endpoint to same path from both the flow
integration-consumer-client1 and integration-consumer-client2
Then in integration-internetsolutionsFlow1
<flow name="integration-internetsolutionsFlow1" doc:name="integration-internetsolutionsFlow1">
<vm:inbound-endpoint exchange-pattern="request-response" path="Your Path" doc:name="VM" connector-ref="vmConnector" />
<logger level="INFO" message="#[message.payload]" doc:name="Logger"/>
<!-- you don't require a setter-getter here -->
</flow>
The path of outbound VM from both the flow integration-consumer-client1 and integration-consumer-client2 should be same..
You no need a scatter-gather here .. since both the flow will disptch the payload to same VM path .. It will be receive by VM inbound endpoint
I have tried creating Megento connector example program as given in the Megento connector vedio link.http://www.youtube.com/watch?v=GCbuqHLCiOg
My flow is:
<magento:config name="MagentoConnector" username="${magento.username}" password="${magento.password}" address="${magento.address}" doc:name="Magento">
<magento:connection-pooling-profile initialisationPolicy="INITIALISE_ONE" exhaustedAction="WHEN_EXHAUSTED_GROW"/>
</magento:config>
<flow name="ShoppingCartOPerations" doc:name="ShoppingCartOPerations">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="shoppingCartOperation" doc:name="HTTP"/>
<flow-ref name="CreateProduct" doc:name="Flow Reference"/>
<set-payload value="Product Id is #[groovy:message.getProperty('productId')]" doc:name="Set Payload"/>
</flow>
<sub-flow name="CreateProduct" doc:name="CreateProduct">
<magento:create-product config-ref="MagentoConnector" type="simple" set="1" sku="simple_sku" storeViewIdOrCode="4" doc:name="Create Product" address="https://sashistore.gostorego.com/api/v2_soap" password="gdskey" username="gdssrao">
<magento:attributes name="SampleProduct" description="TestProduct" short_description="creating sample product" weight="100" status="1" visibility="4" price="100" tax_class_id="1"/>
</magento:create-product>
<set-property propertyName="productId" value="#[payload]" doc:name="Store Product id"/>
<magento:update-inventory-stock-item config-ref="MagentoConnector" productId="#[groovy:message.getProperty('productId')]" doc:name="Update Stock">
<magento:catalog-inventory-stock-item qty="33" is_in_stock="100" min_qty="10"/>
</magento:update-inventory-stock-item>
</sub-flow>
ERROR 2014-01-29 23:48:48,521 [[magentotest].connector.http.mule.default.receiver.02] org.mule.retry.notifiers.ConnectNotifier: Failed to connect/reconnect: Work Descriptor. Root Exception was: null. Type: class org.mule.api.ConnectionException
ERROR 2014-01-29 23:48:48,524 [[magentotest].connector.http.mule.default.receiver.02] org.mule.exception.DefaultMessagingExceptionStrategy:
<magento:config name="MagentoConnector" username="gdssrao" password="gdskey" address="https://sashistore.gostorego.com/api/v2_soap" doc:name="Magento">
<magento:connection-pooling-profile initialisationPolicy="INITIALISE_ONE" exhaustedAction="WHEN_EXHAUSTED_GROW"/>
</magento:config>
<flow name="ShoppingCartOPerationsFlow" doc:name="ShoppingCartOPerationsFlow">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="shoppingCartOperation" doc:name="HTTP"/>
<logger level="INFO" doc:name="Logger"/>
<flow-ref name="CreateProductFlow" doc:name="Flow Reference"/>
<logger level="INFO" doc:name="Logger"/>
<set-payload value="Product Id is #[groovy:message.getProperty('productId')]" doc:name="Set Payload"/>
</flow>
<sub-flow name="CreateProductFlow" doc:name="CreateProductFlow">
<magento:create-product config-ref="MagentoConnector" type="simple" set="1" sku="simple_sku" storeViewIdOrCode="4" doc:name="Create Product">
<magento:attributes name="SampleProduct" description="TestProduct" short_description="creating sample product" weight="100" visibility="4" />
</magento:create-product>
<logger level="INFO" doc:name="Logger"/>
<set-property propertyName="productId" value="#[payload]" doc:name="Store Product id"/>
<logger level="INFO" doc:name="Logger"/>
<magento:update-inventory-stock-item config-ref="MagentoConnector" productId="#[groovy:message.getProperty('productId')]" doc:name="Update Stock">
<magento:catalog-inventory-stock-item />
</magento:update-inventory-stock-item>
</sub-flow>
You have defined your plaintext connection attributes (username, password, address) in magento:create-product and then you have them as application properties in magento:config. That does not really make sense, as you only need to define the attributes once (in the config element) when you use config-ref in the other elements. Since you are having a connection failure, I would guess that you have incorrect properties in the config element. Try using the attributes from magento:create-product, instead.
EDIT: I checked the WSDL for your Magento API, and it seems that you have incorrect address
Try using https://sashistore.gostorego.com/index.php/api/v2_soap/index/ instead.
EDIT2: I got the WSDL URL for Magento API v2 from the Magento documentation. See this page for explanation on how to get the address for Web services from WSDL.