I have a Mule flow which updates Magento Invtory through SOAP API. Everything runs great until I try to update an item which is not in the Magento Database. I then get an exception.
ERROR 2016-06-17 12:31:06,523 [[bwgs-to-magento].bwgs-to-magentoFlow.stage1.02] org.mule.retry.notifiers.ConnectNotifier: Failed to connect/reconnect: Work Descriptor. Root Exception was: Product not exists.. Type: class org.apache.axis.AxisFault
My exception strategy is this:
<choice-exception-strategy doc:name="Choice Exception Strategy">
<catch-exception-strategy when="#[exception.causedExactlyBy(org.mule.api.MessagingException)]" doc:name="Catch Exception Strategy">
<logger message="error" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
</choice-exception-strategy>
My desired result is when an exception occurs, log it, but keep processing the flow.
Edit:
I have also tried the following exception strategy:
<choice-exception-strategy doc:name="Choice Exception Strategy">
<catch-exception-strategy when="#[exception.causeMatches(org.mule.api.*)]" enableNotifications="true" doc:name="Catch Exception Strategy">
<logger message="#[exception.cause.message]" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
</choice-exception-strategy>
Here is the error syntax:
ERROR 2016-06-20 10:47:03,080 [[bwgs-to-magento].bwgs-to-magentoFlow.stage1.02] org.mule.exception.DefaultMessagingExceptionStrategy:
Message : Failed to invoke updateInventoryStockItem. Message payload is of type: String[]
Type : org.mule.api.MessagingException
Code : MULE_ERROR--2
Payload : [Ljava.lang.String;#191acd5
JavaDoc : http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/MessagingException.html
Exception stack is:
1. Product not exists. (org.apache.axis.AxisFault)
org.apache.axis.message.SOAPFaultBuilder:222 (null)
2. Product not exists. (org.mule.module.magento.api.MagentoException)
org.mule.module.magento.api.MagentoClientAdaptor:83 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/module/magento/api/MagentoException.html)
3. Failed to invoke updateInventoryStockItem. Message payload is of type: String[] (org.mule.api.MessagingException)
org.mule.devkit.processor.DevkitBasedMessageProcessor:133 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/MessagingException.html)
The best way to handle this scenario is your flow design. Put the Magento operation and the exception strategy in their own private flow and reference it from another flow. This way the exception will be caught and handled in the private flow and processing will return to the main flow where you can continue doing anything you want. For example:
<flow name="main-flow">
<flow-ref name="magento-flow" />
<logger level="INFO" message="This will continue processing" />
</flow>
<flow name="magento-flow">
<magento ... />
<choice-exception-strategy doc:name="Choice Exception Strategy">
<catch-exception-strategy when="#[exception.causeMatches(org.mule.api.*)]" enableNotifications="true" doc:name="Catch Exception Strategy">
<logger message="#[exception.cause.message]" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
</choice-exception-strategy>
</flow>
In the MagnetoFlow make the flow end at DB level with flowRef and rest of the logic will continue in the next flow.If suppose exception happens it will caught in exception strategy. Here you log the exception and keep continue with the flow Ref of pendingLogic_MagnetoFlow. Check in choice whether the payload is available to continue( because here flow if flow continue from exception payload mightn't present), if so use the sessionVars where you have stored in session variable to continue with other logics.
<flow name="magnetoFlow">
<set-session-variable variableName="originalPayload" value="#[payload]" doc:name="Session Variable"/>
---DB here----
<flow-ref name="pendingLogicFrom_MagnetoFlow" doc:name="Flow Reference"/>
<catch-exception-strategy doc:name="Catch Exception Strategy" when="#[exception.causeMatches(org.mule.api.*)]">
<logger message="#[exception.cause.message]" level="INFO" doc:name="Logger"/>
<flow-ref name="pendingLogicFrom_MagnetoFlow" doc:name="pendingLogicFrom_MagnetoFlow"/>
</catch-exception-strategy>
</flow>
<flow name="pendingLogicFrom_MagnetoFlow">
<choice doc:name="Choice">
<when expression="#[check the payload is empty or not here ]">
<set-payload value="#[seesionVars.originalPayload]" doc:name="Set Payload"/>
</when>
<otherwise>
<logger level="INFO" doc:name="Logger"/>
</otherwise>
</choice>
<logger level="INFO" doc:name="Logger"/>
---other normal logic here ---
</flow>
Check this out.
Related
I'm tryring to set up WS-Security in a CXF Proxy MULE Project. I currently have it working with a properties file, but I would like to take some info out of the properties file and insert it in the DataBase so it can be secured there but I can't find a way to make it work.
The relevant data in my project now looks like this:
CXF Proxy in flow:
<cxf:proxy-service doc:name="CXF Server" wsdlLocation="${wss.http.protocol}://${wss.http.host}:${wss.http.port}${wss.http.base_path}?${wss.http.wsdl_file}" payload="envelope" bindingId="${wss.http.binding_id}" namespace="${wss.http.namespace}" service="${wss.http.service}" >
<cxf:inInterceptors>
<spring:bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
<spring:bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<spring:constructor-arg>
<spring:map>
<spring:entry key="action" value="Signature" />
<spring:entry key="signaturePropFile" value="ws.properties" />
</spring:map>
</spring:constructor-arg>
</spring:bean>
</cxf:inInterceptors>
</cxf:proxy-service>
ws.properties file:
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=JKS
org.apache.ws.security.crypto.merlin.file=myTrustStore.jks
org.apache.ws.security.crypto.merlin.keystore.password=myTrustStorePass
I'd need to take those file and keystore.password parameters out of the files of the project and set them in the DataBase in order to be injected.
I have vainly (as labels like util:properties are throwing a 'The prefix "util" for element "util:properties" is not bound' error) tried an approach similar to the one shown here:
http://cxf.547215.n5.nabble.com/WS-Security-Properties-Reference-td5505704.html
I've also tried to set the properties file this way in order to get the relevant data from the BD, but this data is not getting injected:
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=JKS
org.apache.ws.security.crypto.merlin.file=${wss.trustKeystore.file}
org.apache.ws.security.crypto.merlin.keystore.password=${wss.trustKeystore.password}
Am I doing anything wrong?
Can this be solved in any of the ways exposed (or any other)? If so, how?
Thanks.
EDIT due to a new scenario for this problem:
When I load the configuration for the interceptor from a properties file everything works fine, but I need to inject those configuration properties from DB, so I decided to configure it by using a java.util.properties object in the XML file in order to inject the values later. As a previous step to stablishing the injections, this is the code I have:
<mule xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml"
xmlns:tls="http://www.mulesoft.org/schema/mule/tls"
xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf"
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:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.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/http
http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/cxf
http://www.mulesoft.org/schema/mule/cxf/current/mule-cxf.xsd
http://www.mulesoft.org/schema/mule/tls
http://www.mulesoft.org/schema/mule/tls/current/mule-tls.xsd">
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="5081" doc:name="HTTP Listener Configuration"/>
<http:request-config name="HTTP_Request_Configuration" host="${conf.prop.host}" port="${conf.prop.port}" doc:name="HTTP Request Configuration" connectionIdleTimeout="60000" responseTimeout="60000"/>
<spring:beans>
<spring:bean id="WrongResultException" name="WrongResultException" class="transform.WrongResultException"/>
<spring:bean name="wsCryptoProperties" class="java.util.Properties">
<spring:constructor-arg>
<spring:map>
<spring:entry key="org.apache.ws.security.crypto.provider" value="org.apache.ws.security.components.crypto.Merlin"/>
<spring:entry key="org.apache.ws.security.crypto.merlin.keystore.type" value="JKS"/>
<spring:entry key="org.apache.ws.security.crypto.merlin.keystore.password" value="my_truststore_password"/>
<spring:entry key="org.apache.ws.security.crypto.merlin.file" value="my_truststore.jks"/>
</spring:map>
</spring:constructor-arg>
</spring:bean>
</spring:beans>
<flow name="HttpsCall">
<http:listener config-ref="https-listener-configured-in-domain-app" path="/my_path/my_service" doc:name="HTTPS"/>
<logger message="HTTPS call" level="INFO" doc:name="Logger HTTPS"/>
<flow-ref name="HttpCall" doc:name="HttpCall"/>
</flow>
<flow name="HttpCall">
<http:listener config-ref="http-listener-configured-in-domain-app" path="/my_path/my_service" doc:name="HTTP"/>
<cxf:proxy-service doc:name="CXF Server" wsdlLocation="${service.protocol}://${service.host}:${service.port}${service.base_path}?${service.wsdl_file}" payload="envelope" bindingId="${service.binding_id}" namespace="${service.namespace}" service="${service.service}" >
<cxf:inInterceptors>
<spring:bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
<spring:bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<spring:constructor-arg>
<spring:map>
<spring:entry key="action" value="Signature" />
<!-- This is how the Crypto object is configured when using a properties file
<spring:entry key="signaturePropFile" value="security_conf_file.properties" />-->
<spring:entry key="signaturePropRefId" value="wsCryptoProperties"/>
</spring:map>
</spring:constructor-arg>
</spring:bean>
</cxf:inInterceptors>
</cxf:proxy-service>
<message-properties-transformer doc:name="Message Properties">
<add-message-property key="SOAPAction" value="#[message.inboundProperties.SOAPAction]"/>
</message-properties-transformer>
<cxf:proxy-client payload="envelope" doc:name="CXF Client" />
<http:request config-ref="HTTP_Request_Configuration" path="${service.base_path}" method="POST" doc:name="HTTP" />
<exception-strategy ref="mule-serviceCatch_Exception_Strategy" doc:name="Reference Exception Strategy"/>
</flow>
<catch-exception-strategy name="mule-serviceCatch_Exception_Strategy">
<logger message="Exception: #[message]" level="INFO" doc:name="Logger"/>
<transformer ref="WrongResultException" doc:name="Transformer Reference"/>
<mulexml:object-to-xml-transformer doc:name="Object to XML"/>
</catch-exception-strategy>
The fact is that everything compiles properly even when configuring the properties via java.util.Properties but, when calling to the service, an error is thrown saying that the properties were not loaded correctly:
WARN 2017-05-03 12:08:27,448 [[mule_domain_app].http-listener-configured-in-domain-app.worker.01] org.apache.ws.security.handler.WSHandler: The Crypto reference wsCryptoProperties specified by signaturePropRefId could not be loaded
WARN 2017-05-03 12:08:27,467 [[mule_domain_app].http-listener-configured-in-domain-app.worker.01] org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor:
org.apache.ws.security.WSSecurityException: General security error (WSSecurityEngine: No crypto property file supplied to verify signature)
at
org.apache.ws.security.message.token.X509Security.getX509Certificate(X509Security.java:100) ~[wss4j-1.6.18.jar:1.6.18]
at
org.apache.ws.security.message.token.SecurityTokenReference.getKeyIdentifier(SecurityTokenReference.java:491) ~[wss4j-1.6.18.jar:1.6.18] ...
And so on...
Can anybody throw some light over this issue? I'm completely stuck.
maybe you can provide this two parameters when you are starting your mule runtime.
./mule -M-Dorg.apache.ws.security.crypto.merlin.file=myTrustStore.jks -M-Dorg.apache.ws.security.crypto.merlin.keystore.password=myTrustStorePass
inside your mule configuration file, you should be able to access the values with: ${org.apache.ws.security.crypto.merlin.file} and ${org.apache.ws.security.crypto.merlin.keystore.password}
Not pretty sure if this would be a valid solution in your use case but maybe it could give you new ideas...
Let's see if this will solve the problem... I could replicate the case of getting values from a database and setup a connector. I made it slightly different but I guess that the concept is the only important matter.
In my case, I get properties from a derby in memory database and then I use this props for setting up an http:listener-config
First, I added a springBean to hold my properties:
<spring:beans>
<spring:bean id="propertiesBean" name="propertiesBean" class="com.mmartinez.test.DerbyLoadProperties" />
</spring:beans>
Inside the DerbyLoadProperties class, is necessary to implements InitializingBean and FactoryBean. The factoryBean will allow you to return the Properties object containing your properties, in this case coming from the database.
public class DerbyLoadProperties implements InitializingBean, FactoryBean {
private Properties prop = new Properties();
#Override
public void afterPropertiesSet() throws Exception {
initializeDatabaseAndExtractProperties();
//Inside this method I initialize the in-memory-db and also add the host and port properties from DB
//prop.put("http.hostmario", host);
//prop.put("http.portmario", port);
}
#Override
public Class getObjectType() {
return Properties.class;
}
#Override
public Object getObject() throws Exception {
return prop;
}
#Override
public boolean isSingleton() {
return false;
}
Now I can use my propertiesBean as a property-placeholder
<context:property-placeholder properties-ref="propertiesBean" />
In the last step, I will setup my http:listener-config, in your case the cxf:proxy-service....
<http:listener-config port="${http.portmario}" host="${http.hostmario}" name="testListener" doc:name="HTTP Listener Configuration" />
Is working fine for me.
Solved!
This line was missing beetween the entries of the map passed in the WSS4JInInterceptor constructor:
<spring:entry key="wsCryptoProperties" value-ref="wsCryptoProperties"/>
Doing this, an injection in the values of the props of the java.util.Properties object works as a charm.
Hope this helps anybody in the future!
I have two separate messages being published to a staging.queue. I want the JMS consumer of the staging queue to wait 10 seconds before consumer all the messages from the staging.queue. I have the following strategy:
<jms:activemq-connector name="Active_MQ" username="admin" password="admin" brokerURL="tcp://localhost:61616" validateConnections="true" doc:name="Active MQ">
<service-overrides transactedMessageReceiver="com.mulesoft.mule.transport.jms.TransactedPollingJmsMessageReceiver" />
</jms:activemq-connector>
<flow name="integration-consumer-client2" doc:name="integration-consumer-client2">
<jms:inbound-endpoint queue="client2.publish" connector-ref="Active_MQ" doc:name="JMS">
</jms:inbound-endpoint>
<logger message="Consumes Client 2 = #[payload]" level="INFO" doc:name="Logger"/>
<logger message="Client 2 Correlation = #[message.correlationId] and Correlation sequence = #[message.correlationSequence]" level="INFO" doc:name="Logger"/>
<json:object-to-json-transformer doc:name="Object to JSON"/>
<jms:outbound-endpoint queue="waiting.queue" connector-ref="Active_MQ" doc:name="JMS"/>
</flow>
<flow name="integration-consumer-client" doc:name="integration-consumer-client">
<jms:inbound-endpoint doc:name="JMS" connector-ref="Active_MQ" queue="client1.publish">
</jms:inbound-endpoint>
<logger message="Consumes Client 1 = #[payload]" level="INFO" doc:name="Logger"/>
<logger message="Client Correlation = #[message.correlationId] and Correlation sequence = #[message.correlationSequence]" level="INFO" doc:name="Logger"/>
<json:object-to-json-transformer doc:name="Object to JSON"/>
<jms:outbound-endpoint queue="waiting.queue" connector-ref="Active_MQ" doc:name="JMS"/>
</flow>
<flow name="integration-Flow3" doc:name="integration-Flow3">
<jms:inbound-endpoint queue="staging.queue" connector-ref="Active_MQ" doc:name="JMS">
<properties>
<spring:entry key="pollingFrequency" value="10000" />
</properties>
</jms:inbound-endpoint>
<logger message="after poller = #[payload]" level="INFO" doc:name="Logger"/>
</flow>
but the consumer doesn't wait 10 seconds. it consumes the messages immediately
You can do it by following way :-
Make integration-Flow3 as a sub flow
Use flow-ref to call the subflow integration-Flow3 after jms:outbound-endpoint of both the flow :- integration-consumer-client2 and integration-consumer-client
Now in the beginning of subflow integration-Flow3 remove JMS inbound endpoint and use a Groovy Script where you can define sleep(Your time)
Then after Groovy Script use Mule Module Requester component to call the JMS inbound endpoint ..
Mule Module Requester is the component that can able to call any inbound endpoint in the middle of the flow ..
You can found details of Mule Module Requester here https://github.com/mulesoft/mule-module-requester and http://blogs.mulesoft.org/introducing-the-mule-requester-module/
Just use it to call JMS inbound endpoint with queue="staging.queue" ..
Since you will be using GroovyScript before Mule Module Requester .. Groovy script will take care of holding the timer .. (You need to set sleep() method inside your Groovy Script ) .. That's all
currently I am working with mule and need to write in WMQ Queue. But instead of using WMQ endpoint, I want to do it by using JMS Endpoint. Here is my configuration:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:jms="http://www.mulesoft.org/schema/mule/jms" xmlns:jetty="http://www.mulesoft.org/schema/mule/jetty" xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting" xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns:wmq="http://www.mulesoft.org/schema/mule/ee/wmq" xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:json="http://www.mulesoft.org/schema/mule/json" xmlns:data-mapper="http://www.mulesoft.org/schema/mule/ee/data-mapper" xmlns:ajax="http://www.mulesoft.org/schema/mule/ajax" xmlns:jersey="http://www.mulesoft.org/schema/mule/jersey" 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.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/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/jersey http://www.mulesoft.org/schema/mule/jersey/current/mule-jersey.xsd
http://www.mulesoft.org/schema/mule/ajax http://www.mulesoft.org/schema/mule/ajax/current/mule-ajax.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/json http://www.mulesoft.org/schema/mule/json/current/mule-json.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/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd
http://www.mulesoft.org/schema/mule/ee/wmq http://www.mulesoft.org/schema/mule/ee/wmq/current/mule-wmq-ee.xsd
http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd
http://www.mulesoft.org/schema/mule/jetty http://www.mulesoft.org/schema/mule/jetty/current/mule-jetty.xsd
http://www.mulesoft.org/schema/mule/jms http://www.mulesoft.org/schema/mule/jms/current/mule-jms.xsd">
<wmq:connector name="WMQ" hostName="localhost" port="1414" queueManager="localmanager" validateConnections="true" doc:name="WMQ" ccsId="819"/>
<data-mapper:config name="map_to_xml" transformationGraphPath="map_to_xml.grf" doc:name="map_to_xml"/>
<data-mapper:config name="xml_to_json" transformationGraphPath="xml_to_json.grf" doc:name="xml_to_json"/>
<jms:connector name="jmsConnector"
connectionFactoryJndiName="jms/ConnectionFactory"
jndiInitialFactory="com.ibm.websphere.naming.WsnInitialContextFactory"
specification="1.1"
connectionFactory-ref="MQConnectionFactory">
<spring:property name="jmsSupport" ref="customJmsSupport"/>
</jms:connector>
<spring:beans>
<spring:bean id="customJmsSupport" class="CustomJms11Support">
<spring:constructor-arg ref="jmsConnector" />
</spring:bean>
<spring:bean name="MQConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<spring:property name="hostName" value="localhost"/>
<spring:property name="port" value="1414"/>
<spring:property name="queueManager" value="localmanager"/>
<spring:property name="transportType" value="1"/>
</spring:bean>
</spring:beans>
<flow name="RequestFlow" doc:name="RequestFlow">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8088" path="uebermittleAusweisdaten" doc:name="HTTP" contentType="text/html"/>
<expression-filter expression="#[message.payload !='/favicon.ico']" doc:name="Expression"/>
<jersey:resources doc:name="REST">
<component class="de.fraport.sources.RestClass"/>
</jersey:resources>
<set-variable variableName="id" value="#[message.id]" doc:name="Message ID"/>
<json:json-to-object-transformer returnClass="java.util.Map" doc:name="JSON to Object"/>
<data-mapper:transform config-ref="map_to_xml" doc:name="Map To XML">
<data-mapper:input-arguments>
<data-mapper:input-argument key="id">#[flowVars['id']]</data-mapper:input-argument>
</data-mapper:input-arguments>
</data-mapper:transform>
<flow-ref name="Subflow1" doc:name="Flow Reference"/>
<parse-template location="D:\Workspace\ajax_rest\src\main\app\www\index.html" doc:name="Parse Template"/>
</flow>
<sub-flow name="Subflow1" doc:name="Subflow1">
<mulexml:xslt-transformer encoding="ISO8859-1" maxIdleTransformers="2" maxActiveTransformers="5" xsl-file="D:\Workspace\ajax_rest\mobako.sender.xsl" doc:name="SOAP Envelope"/>
<mulexml:dom-to-xml-transformer outputEncoding="ISO8859-1" doc:name="DOM to XML"/>
<outbound-endpoint doc:name="JMS" address="jms://LSMH.ZKSEAP.SERVICEBUS" connector-ref="jmsConnector" encoding="ISO8859-1"/>
<!-- <wmq:outbound-endpoint queue="LSMH.ZKSEAP.SERVICEBUS" encoding="ISO8859-1" connector-ref="WMQ" doc:name="ZKSEAP IN"/> -->
<set-property propertyName="MULE_CORRELATION_ID" value="#[function:dateStamp:yyyy-MM-dd HH:mm:ss]" doc:name="Set Correlation ID"/>
<request-reply>
<vm:outbound-endpoint path="sender">
<message-properties-transformer scope="outbound">
<delete-message-property key="MULE_REPLYTO"/>
</message-properties-transformer>
</vm:outbound-endpoint>
<vm:inbound-endpoint path="response">
<logger level="INFO" message="#[string:XXXXXX 1: #[message.inboundProperties]"/>
</vm:inbound-endpoint>
</request-reply>
</sub-flow>
<flow name="ResponseFlow" doc:name="ResponseFlow">
<inbound-endpoint address="jms://ZKSEAP.LSMH.SERVICEBUS" connector-ref="jmsConnector" doc:name="ZKSEAP OUT"/>
<!-- <wmq:inbound-endpoint queue="ZKSEAP.LSMH.SERVICEBUS" connector-ref="WMQ" doc:name="ZKSEAP OUT" encoding="UTF-8"/> -->
<set-property propertyName="MULE_CORRELATION_ID" value="#[function:dateStamp:yyyy-MM-dd HH:mm:ss]" doc:name="Set Correlation ID"/>
<data-mapper:transform doc:name="XML To JSON" config-ref="xml_to_json"/>
<byte-array-to-string-transformer doc:name="Byte Array to String"/>
<vm:outbound-endpoint path="response" doc:name="Response Outbound" exchange-pattern="one-way"/>
</flow>
</mule>
I have successfully read message from WMQ Queue by using JMS endpoint. However, when I tried to write some message in WMQ Queue by using JMS Endpoint, I got following error from my server:
2014-07-22 10:11:27,064 [Axis2 Task] ERROR WMQMsg - Expected MQ
message format ' MQSTR ', but received 'MQHRF2 ' 2014-07-22
10:11:27,064 [Axis2 Task] WARN QMgrConnection - Moving msg into dead
letter queue after 1 try/tries:
414D51206C6F63616C6D616E616765721A0CCE5320003C0 2 [Fatal Error] :1:1:
Content ist nicht zulõssig in Prolog. ERROR: 'Content ist nicht
zulõssig in Prolog.' 2014-07-22 10:11:27,064 [Axis2 Task] WARN ESBMsg
- Error prettifying ESBMsg for log printing
I know that this error occured because I tried to write into Non-JMS Queue. Also I know that I have to solve it by setting "?targetClient=1". However, when I tried to add the targetClient attribute into my Queue URL, I still got the error (it seems that the attribute was recognized as URL too by WMQ).
Then, from my research, I found out that I can not directly set the "?targetClient" in the url. Instead of that, I need to create a Java Class to set the "?targetClient". To create those class, I follow some instructions from following URL
Create Custom JMSSupport Class
But unfortunatelly, it also did not work for me. Anyone has an idea about how can I solve it? Thanks.
NB: In Apache Camel, I can simply solve it by adding:
<setHeader headerName="CamelJmsDestinationName">
<constant>queue:///LSMH.ZKSEAP.SERVICEBUS?targetClient=1</constant>
</setHeader>
Is there something similar in Mule ESB?
Just solved the problem:
It is right that we need to create a java class to set the targetClient. And to do so, we can follow the link that I gave above. However, we will need to change the code a bit.
Here is the right code:
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Session;
import org.mule.api.endpoint.ImmutableEndpoint;
import org.mule.transport.jms.Jms11Support;
import org.mule.transport.jms.JmsConnector;
import com.ibm.mq.jms.JMSC;
import com.ibm.mq.jms.MQQueue;
/**
* Implements WebSphere MQ specific JMS support for Mule. The class
* overrides the createDestination method to intercept JMS Queue object
* creation and sets the targetClient=1 property on created MQQueue
* objects. This is necessary to prevent non-JMS consumers from being
* choked by RFH2 headers.
*/
public class CustomJms11Support extends Jms11Support {
public CustomJms11Support(JmsConnector connector) {
super(connector);
}
#Override
public Destination createDestination(Session session, String name, boolean
topic, ImmutableEndpoint ie) throws JMSException {
Destination destination = super.createDestination(session, name, topic, ie);
if (destination instanceof MQQueue){
((MQQueue) destination).setTargetClient(JMSC.MQJMS_CLIENT_NONJMS_MQ);
}
return destination;
}
}
And then, we will need to set a property called "JMS_IBM_Character_Set" (If not we will get "Expected MQ message characterSet '819', but received '1208'" error) before send the request to JMS endpoint. Here is how I configure it:
<set-property propertyName="JMS_IBM_Character_Set" value="ISO8859_1" doc:name="Property"/>
And just for your information, by changing the WMQ endpoint to JMS endpoint, for sure it improve the performance.
Hopefully it would be useful :D
I'm using mule standalone 3.4. I am trying to create a flow using the Salesforce connector to perform a query operation and then pass the payload to a spring component. The result is the component doesn't get called.
<flow name="sfcdContact" doc:name="sfcdContact">
<quartz:inbound-endpoint repeatInterval="2000"
startDelay="3000"
jobName="sfcdContact">
<quartz:event-generator-job/>
</quartz:inbound-endpoint>
<sfdc:query config-ref="Salesforce"
query="${salesforce.query.contact}"
doc:name="sfcdContactQuery"/>
<component>
<spring-object bean="salesForceConsumer"/>
</component>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<flow-ref name="ErrorHandling"/>
</catch-exception-strategy>
</flow>
If I remove the sfdc portion from the flow, the spring component is successfully invoked. If I remove the component portion from the flow and replace it with:
<logger message="\#\#\# query operation payload \#[payload]" level="INFO" doc:name="Logger"/>
The results are successfully entered into the log. So it seems the pieces work correctly individually.
I have the logs set to debug, and no errors are reported.
Here's the Java code:
public class SalesForceConsumer {
public Object consume(#Payload Object payload) throws Exception {
System.out.println("SalesForceConsumer::consume called");
return payload;
}
}
I also tried modifying the signature to:
public Object consume(#Payload HashMap<String,Object> payload)
Which is what the doc indicates is returned from the connector.
Is there any reason why the Salesforce connector can't be combined with a bean, or do I have it configured incorrectly? Thank-you.
I ran your code on Mule EE 3.4 and it worked just fine.
The console output:
INFO 2015-03-26 18:37:51,903 org.mule.api.processor.LoggerMessageProcessor: \#\#\# query operation payload \[{FirstName=Test, Id=null, type=Contact}]
SalesForceConsumer::consume called
The flow:
<spring:beans>
<spring:bean id="salesForceConsumer" name="salesForceConsumer" class="com.acme.util.SalesForceConsumer"/>
</spring:beans>
<sfdc:config name="Salesforce" username="XXXX" password="XXXX" securityToken="XXXX" url="https://login.salesforce.com/services/Soap/u/28.0" doc:name="Salesforce">
<sfdc:connection-pooling-profile initialisationPolicy="INITIALISE_ONE" exhaustedAction="WHEN_EXHAUSTED_GROW"/>
</sfdc:config>
<flow name="sfcdContact" doc:name="sfcdContact">
<quartz:inbound-endpoint repeatInterval="2000" startDelay="3000" jobName="sfcdContact">
<quartz:event-generator-job/>
</quartz:inbound-endpoint>
<sfdc:query config-ref="Salesforce" query="select FirstName from Contact" doc:name="sfcdContactQuery"/>
<logger message="\#\#\# query operation payload \#[payload]" level="INFO" doc:name="Logger"/>
<component>
<spring-object bean="salesForceConsumer"/>
</component>
</flow>
I have got simple setup of mule. Reading from JMS queue processing message and in case of exception sending to DLQ. With Mule 3.3.0 and HornetQ 2.3.0.BETA1. I am getting following exception:
Caused by: java.lang.ClassCastException: org.mule.transport.jms.ReusableTopicSessionWrapper cannot be cast to javax.jms.QueueSession
at org.mule.transport.jms.Jms102bSupport.createDestination(Jms102bSupport.java:231)
at org.mule.transport.jms.Jms11Support.createDestination(Jms11Support.java:142)
at org.mule.transport.jms.JmsMessageDispatcher.dispatchMessage(JmsMessageDispatcher.java:163)
at org.mule.transport.jms.JmsMessageDispatcher.doDispatch(JmsMessageDispatcher.java:81)
at org.mule.transport.AbstractMessageDispatcher.process(AbstractMessageDispatcher.java:99)
... 113 more
My setup:
<jms:connector name="connector.jms" maxRedelivery="10" doc:name="JMS"
jndiInitialFactory="org.jnp.interfaces.NamingContextFactory"
jndiProviderUrl="jnp://localhost:1099"
connectionFactoryJndiName="ConnectionFactory"
createMultipleTransactedReceivers="true"
numberOfConcurrentTransactedReceivers="100"
acknowledgementMode="AUTO_ACKNOWLEDGE">
<reconnect-forever frequency="5000"/>
</jms:connector>
<flow name="jmsListenerFlow1" doc:name="jmsListenerFlow1">
<jms:inbound-endpoint queue="adsLogQueue" connector-ref="connector.jms" doc:name="JMS">
<jms:transaction action="ALWAYS_BEGIN"/>
</jms:inbound-endpoint>
<component >
<spring-object bean="logSaver"/>
</component>
<catch-exception-strategy>
<jms:outbound-endpoint queue="DLQ"> <!-- [2] -->
<jms:transaction action="ALWAYS_JOIN" />
</jms:outbound-endpoint>
</catch-exception-strategy>
</flow>
Can it be bug in Mule itself ? Or am I doing something wrong?
Set specification="1.1" on the jms:connector.