Configuring JMS connectionfactory in mule - jms

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.

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!

High Efficient MDB using spring jms or ntegration

I have requirement where I need receive message from MQ every seconds , the message will be in XML format , so i need to write a high effecient MDB. Problem here is I am new to MQ,JMS,Spring JMS and Spring Integration but not spring tough.
Based on google search so far I am able to write below code
MDB
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
public class MyMessageListener implements MessageListener{
#Override
public void onMessage(Message m) {
TextMessage message=(TextMessage)m;
try{
System.out.println(message.getText());
}catch (Exception e) {e.printStackTrace(); }
}
}
XMl 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:jms="http://www.springframework.org/schema/jms"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms.xsd">
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"
p:brokerURL="tcp://localhost:61616" />
<bean id="listener" class="com.springexample.MyMessageListener"></bean>
<jms:listener-container container-type="default" connection-factory="connectionFactory"
acknowledge="auto">
<jms:listener destination="myfirstqueue" ref="listener" method="onMessage"></jms:listener>
</jms:listener-container>
</beans>
I know what i have written is very basic one but i dont know what is the efficient one , how to provide transaction support and how to handle such load where i am going to recieve message every seconds.
Should i use Spring JMS or Spring Integration any help is much appreciated.
The question you asked is which to use: definitely go Spring JMS

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.

Mule ESB: Setup JMS Endpoint for WMQ Queue

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

Use of Spring Framework for RabbitMQ is reducing the performance

I have created a producer, which was using com.rabbitmq.client.connectionFactory and was sending 1,000,000 messages (40 Bytes) in 100 seconds.
But now I want an spring abstraction. I was unable to use com.rabbitmq.client.connectionFactory rather I had to use org.springframework.amqp.rabbit.connection.SingleConnectionFactory. Using this connection factory only 100,000 messages (40 Bytes) are send to the broker in 100 seconds.
Does anybody have experience why the performance is reduced so much (around 90%).
The code using "import com.rabbitmq.client.ConnectionFactory;" is ->
package Multiple_queues_multiple_consumers;
import java.io.IOException;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Producer {
private static Connection myConnection;
private static Channel myChannel;
public static String myQueueName;
public static void main(String[] args) throws IOException {
long startTime=0;
int count=0;
ConnectionFactory myFactory=new ConnectionFactory();
myFactory.setHost("localhost");
try {
myConnection = myFactory.newConnection();
myChannel = myConnection.createChannel();
String myExchange = "wxyzabc";
String myBody = "This is a message : message numberxxxxxx";
String myRoutingKey = "RoutingKey";
myQueueName = "new_Queue";
myChannel.exchangeDeclare(myExchange, "direct", true, false, null);
myChannel.queueDeclare(myQueueName, true, false, false, null);
myChannel.queueBind(myQueueName, myExchange, myRoutingKey);
startTime=System.currentTimeMillis();
AMQP.BasicProperties properties = new AMQP.BasicProperties();
properties.setDeliveryMode(2);
startTime=System.currentTimeMillis();
while(count++<=10000){
myChannel.basicPublish(myExchange, myRoutingKey, true, true, properties, myBody.getBytes() );
}
System.out.println(System.currentTimeMillis()-startTime);
} catch (Exception e){
System.exit(0);
}
}
}
The code using SpringFramework is :->
Producer1.java
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Producer1 {
public static void main(String[] args) {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("Producer1.xml");
AmqpAdmin amqpAdmin = context.getBean(RabbitAdmin.class);
Queue queue = new Queue("sampleQueue");
DirectExchange exchange = new DirectExchange("myExchange");
Binding binding = new Binding(queue, exchange, "");
amqpAdmin.declareQueue(queue);
amqpAdmin.declareExchange(exchange);
amqpAdmin.declareBinding(binding);
RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);
String routingKey = "";
String myBody = "This is a message : message numberxxxxxx";
Message Msg = new Message(myBody.getBytes(), null);
int count=0;
long CurrTime = System.currentTimeMillis();
while(count++<=10000){
rabbitTemplate.send(routingKey, Msg);
//System.out.println("Message Sent");
}
System.out.println(System.currentTimeMillis()-CurrTime);
}
}
Producer1.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Define a connectionFactory -->
<bean id="rabbitConnectionFactory" class="com.rabbitmq.client.ConnectionFactory">
<property name="host" value="localhost" />
</bean>
<bean id="connectionFactory" class="org.springframework.amqp.rabbit.connection.SingleConnectionFactory">
<constructor-arg ref="rabbitConnectionFactory"/>
</bean>
<!-- Tell the Admin bean about that connectionFactory and initialize it, create a queue and an exchange on Rabbit Broker using the RabbitTemplate provided by Spring framework-Rabbit APIs -->
<bean id="Admin" class="org.springframework.amqp.rabbit.core.RabbitAdmin">
<constructor-arg ref="connectionFactory" />
</bean>
<bean id="rabbitTemplate" class="org.springframework.amqp.rabbit.core.RabbitTemplate"
p:connectionFactory-ref="connectionFactory"
p:routingKey="myRoutingKey"
p:exchange="myExchange" />
</beans>
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- Define a connectionFactory -->
<bean id="connectionFactory" class="com.rabbitmq.client.connectionFactory">
<constructor-arg value="localhost" />
<property name="username" value="guest" />
<property name="password" value="guest" />
</bean>
<bean id="Admin" class="org.springframework.amqp.rabbit.core.RabbitAdmin">
<constructor-arg ref="connectionFactory" />
</bean>
</beans>
Using this xml file, the error appears saying org.springframework.amqp.rabbit.core.RabbitAdmin could not cast com.rabbitmq.client.connectionFactory for connectionfactory bean.
The exact error is: "nested exception is java.lang.IllegalStateException: Cannot convert value of type [com.rabbitmq.client.ConnectionFactory] to required type [org.springframework.amqp.rabbit.core.RabbitTemplate]: no matching editors or conversion strategy found" .
Hence i have to use bean:
<bean id="connectionFactory"
class="org.springframework.amqp.rabbit.connection.SingleConnectionFactory">
</bean>
Are you sure that you used the same Rabbit MQ broker? Could you be using a broker on a different server, or an upgraded/downgraded version of RabbitMQ?
The other thing to look at is your jvm. Is it possible that you don't have enough memory configured and now the garbage collector is thrashing? Run top and see if the jvm's memory usage is close to the configured memory size.
Are you using an old version of RabbitMQ. Lots of Linux distros include RabbitMQ 1.7.2 which is an old version that has problems with large numbers of messages. Large is hard to define because it depends on your RAM, but RabbitMQ does not like to use more than 40% of RAM because it needs to copy a persistence transaction log in order to process it and clean it for log rollover. This can cause RabbitMQ to crash, and, of course, processing the huge logs will slow it down. RabbitMQ 2.4.1 handles the persister logs much better, in smaller chunks, and it also has much, much faster message routing code.
This still sounds to me like a Java problem, either Spring is just a pig and is terribly inefficient, or you have not given your jvm enough RAM to avoid frequent gc runs. What setting are you using for -Xmx?

Resources