Mule ESB: Setup JMS Endpoint for WMQ Queue - jms

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

Related

Setting up WS-Security in MULE without properties file (WSS4JInInterceptor with signaturePropRefId)

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!

Spring integration file outbound-gateway and webService

I'm new in Spring Integration and i've been triyng some examples on the net, and I found that very helpful repo on github :
spring-integration-samples
For a better anderstanding I tried combinig some example, but then got stuck, my goal was to use the example of ws-inbound-gateway with the file example in order to create a file with the WS request text using the file outbound-gateway and then send back the response of the WS.
For that I did the folowing modifications to the inbound-gateway-config.xml of the ws-inbound-gateway example:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-ws="http://www.springframework.org/schema/integration/ws"
xmlns:int-file="http://www.springframework.org/schema/integration/file"
xsi:schemaLocation="http://www.springframework.org/schema/integration/ws http://www.springframework.org/schema/integration/ws/spring-integration-ws.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/file
http://www.springframework.org/schema/integration/file/spring-integration-file.xsd">
<int:channel id="input"/>
<int-ws:inbound-gateway id="ws-inbound-gateway" request-channel="input"/>
<int-file:outbound-gateway id="mover" request-channel="input"
reply-channel="output"
directory="file:${java.io.tmpdir}/spring-integration-samples/output" />
<int:channel id="output"/>
<int:service-activator input-channel="output">
<bean class="org.springframework.integration.samples.ws.SimpleEchoResponder"/>
</int:service-activator>
</beans>
The rest still the same.
Unfortunally i get bthe following Exception when i try to send a request to the WS:
org.springframework.ws.client.WebServiceTransportException: Erreur Interne de Servlet [500]
at org.springframework.ws.client.core.WebServiceTemplate.handleError(WebServiceTemplate.java:695)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:606)
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:555)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:506)
at org.springframework.ws.client.core.WebServiceTemplate.sendSourceAndReceiveToResult(WebServiceTemplate.java:446)
at org.springframework.ws.client.core.WebServiceTemplate.sendSourceAndReceiveToResult(WebServiceTemplate.java:429)
at org.springframework.integration.samples.ws.InContainerTests.testWebServiceRequestAndResponse(InContainerTests.java:52)
and then when i tried entring the link in my browser i got:
cause mère
org.xml.sax.SAXParseException; lineNumber: 20; columnNumber: 75; cvc-complex-type.2.4.c : Le caractère générique concordant est strict, mais aucune déclaration ne peut être trouvée pour l'élément 'int-file:outbound-gateway'.
com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)
com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)
com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:437)
com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:368)
com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:325)
...
I don't know if I'm missing a declaration in my web.xml or am I getting the chanelling wrong.
Thanks in advence ^^
Using a transformer to transform the DOM message to a String message and the send it to a service activator. like so:
<int-ws:inbound-gateway id="ws-inbound-gateway" request-channel="input"/>
<int:channel id="input"/>
<int:transformer input-channel="input" output-channel="transform" >
<bean class="org.springframework.integration.samples.ws.SimpleTransformerResponder"/>
</int:transformer>
<int:channel id="transform"/>
<int:service-activator input-channel="transform" output-channel="next">
<bean class="org.springframework.integration.file.FileWritingMessageHandler" >
<constructor-arg name="destinationDirectory" value="file:${java.io.tmpdir}/"/>
</bean>
</int:service-activator>
<int:channel id="next"/>
<int:service-activator input-channel="next">
<bean class="org.springframework.integration.samples.ws.SimpleEchoResponder" />
</int:service-activator>
the transformer bean:
public class SimpleTransformerResponder {
public String transform(DOMSource request) {
return request.getNode().getTextContent();
}
}
and the response bean
public class SimpleEchoResponder {
public Source issueResponseFor(File request) {
return new DomSourceFactory().createSource(
"<echoResponse xmlns=\"http://www.springframework.org/spring-ws/samples/echo\">" +
request.getAbsoluteFile() + "</echoResponse>");
}
}
the result is a file with the content of the initial message created, and the response contains the path of the file created.
"Learning hard ^^ "

Spring integration and AMQP on RabbitMQ throws exception Method handleToken(byte[]) cannot be found

This is my context config:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int-amqp="http://www.springframework.org/schema/integration/amqp"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/integration/amqp http://www.springframework.org/schema/integration/amqp/spring-integration-amqp.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
<rabbit:connection-factory id="connectionFactory" host="localhost"/>
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory"/>
<rabbit:queue name="upload-queue"/>
<rabbit:admin connection-factory="connectionFactory"/>
<rabbit:topic-exchange name="infrastructure-exchange">
<rabbit:bindings>
<rabbit:binding queue="upload-queue" pattern="ru.interosite.*"/>
</rabbit:bindings>
</rabbit:topic-exchange>
<int-amqp:outbound-channel-adapter
channel="toRabbit"
routing-key="ru.interosite.1"
amqp-template="amqpTemplate"
exchange-name="infrastructure-exchange"/>
<int-amqp:inbound-channel-adapter
channel="fromRabbit"
queue-names="upload-queue"
connection-factory="connectionFactory"
/>
<int:gateway id="infrastructureGateway" service-interface="com.dropbyke.web.api.service.InfrastructureGateway"/>
<int:channel id="toRabbit"/>
<int:channel id="fromRabbit"/>
<bean id="testInfrastructureServiceImpl" class="com.dropbyke.web.api.service.TestInfrastructureServiceImpl"/>
<int:service-activator input-channel="fromRabbit" ref="testInfrastructureServiceImpl" method="handleToken" />
<!-- A Spring Integration adapter that routes messages sent to the helloWorldChannel to the bean named "helloServiceImpl"'s hello() method -->
<!--<int:outbound-channel-adapter channel="fromRabbit" ref="testInfrastructureServiceImpl" method="handleToken"/>-->
</beans>
This is gateway interface:
public interface InfrastructureGateway {
#Gateway(requestChannel = "toRabbit")
void doUpload(UserTokenDTO tokenDTO);
}
Message endpoint that supposed to handle calls:
#MessageEndpoint
public class TestInfrastructureServiceImpl implements TestInfrastructureService {
public void handleToken( UserTokenDTO tokenDTO) {
System.out.println("Handle user token " + tokenDTO.getToken());
}
}
So when I invoke gateway's doUpload method I'm getting this error message:
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1004E:(pos 8): Method call: Method handleToken(byte[]) cannot be found on com.dropbyke.web.api.service.TestInfrastructureServiceImpl type
If I exclude Rabbit part then all works fine. What should I do to make it work with Rabbit? Should I implement some converter from byte[] to my domain object UserTokenDTO?
As nicolas-labrot suggested I had to make my UserTokenDTO to be a Serializable. After that all works fine.

Configuring JMS connectionfactory in mule

Could anyone suggest me how to configure connectionfactory in mule using connectionFactory-ref
I am trying to configure connectionfactory in mule using connectionFactory-ref[this is the url I am following ::: http://www.mulesoft.org/documentation-3.2/display/32X/JMS+Transport+Reference].
In the above mentioned documentation - mentioned -
Configuring the ConnectionFactory
One of the most important attributes is connectionFactory-ref. This is a reference to the ConnectionFactory object which creates new connections for your JMS provider. The object must implement the interface javax.jms.ConnectionFactory.
ConnectionFactory
So to implement the above below is my mule configuraion xml
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:smtps="http://www.mulesoft.org/schema/mule/smtps"
xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting" xmlns:https="http://www.mulesoft.org/schema/mule/https"
xmlns:http="http://www.mulesoft.org/schema/mule/http" 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.5.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/smtps http://www.mulesoft.org/schema/mule/smtps/current/mule-smtps.xsd
http://www.mulesoft.org/schema/mule/https http://www.mulesoft.org/schema/mule/https/current/mule-https.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/jms http://www.mulesoft.org/schema/mule/jms/current/mule-jms.xsd
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd">
<spring:bean name="connectionFactory" class="com.ers.connections.ConnectionFactoryImpl"/>
<jms:activemq-connector name="Active_MQForApex" connectionFactory-ref="connectionFactory" validateConnections="true" doc:name="Active MQ"/>
<flow name="apexwritequeueFlow1" doc:name="apexwritequeueFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="niviTest" doc:name="HTTP"/>
<logger message="Payload ::: #[payload]" level="INFO" doc:name="Logger"/>
<jms:outbound-endpoint queue="ANS.RecOps.Incoming" connector-ref="Active_MQForApex" doc:name="JMS"/>
</flow>
</mule>
Below java class
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import org.apache.activemq.ActiveMQConnectionFactory;
public class ConnectionFactoryImpl implements javax.jms.ConnectionFactory {
#Override
public Connection createConnection() throws JMSException {
// Create a ConnectionFactory
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("21233", "123", "ssl://xxxx.autonet-yyy.com:443");
return connectionFactory.createConnection();
}
#Override
public Connection createConnection(String arg0, String arg1)
throws JMSException {
// TODO Auto-generated method stub
return null;
}
}
However I am getting this error
. Root Exception was: Unsupported ConnectionFactory type: com.ers.connections.ConnectionFactoryImpl. Type: class java.lang.IllegalArgumentException
ERROR 2014-12-28 11:53:26,141 [main] org.mule.module.launcher.application.DefaultMuleApplication: null
java.lang.IllegalArgumentException: Unsupported ConnectionFactory type: com.ers.connections.ConnectionFactoryImpl
Thank you in advance.
Any suggestions most appreciated.
Thank you and regards
Nivi
If you don't have any really good reason, that you do not show in the post, to write your own ConenctionFactory implementation you should use the one provided by the JMS provider directly.
So you should use a bean definition like this
<spring:bean id="connectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
</spring:bean>
You are using the ActiveMQ connector and it is expecting a factory class of type org.apache.activemq.ActiveMQConnectionFactory. If you really need a custom factory, your ConnectionFactoryImpl class should extend the activemq factory:
import org.apache.activemq.ActiveMQConnectionFactory;
public class ConnectionFactoryImpl extends ActiveMQConnectionFactory {
// Override the methods you need
}
Then you can reference it in connectionFactory-ref attribute of the connector.
Your implementation probably does not provide any special feature, if this is the case please just use the default connector:
<jms:activemq-connector name="JmsConnector" specification="1.1" />
However if you have some special behaviour that you want to use, with the activemq connector, you just need a connection factory that implements org.apache.activemq.ActiveMQConnectionFactory, this is because these two lines. Then just use something like the following:
<spring:beans>
<spring:bean name="myActiveMqConnectionFactory"
class="org.apache.activemq.spring.MyActiveMQConnectionFactory"
p:brokerURL="vm://esb-amq-broker" <--- Just some example property />
</spring:beans>
<jms:activemq-connector name="myJmsConnector"
specification="1.1"
connectionFactory-ref="AmqConnectionFactory"
persistentDelivery="true" />
However please twink twice about the need of doing this, the original activemq connector probably provides almost anything you need with the exeption of connection caching. If that is what you need please consider using this.

inbound and outband JMS queue mule class cast

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.

Resources