I have proxy that listens to JMS queue on message broker. When I send the message to a queue, I set custom properties to JMS message. But when I log the message received by the proxy, there is no custom JMS properties. How would I get custom JMS properties in proxy?
I use WSO2 ESB 4.6.0 with ActiveMQ 5.8.0.
<proxy xmlns="http://ws.apache.org/ns/synapse" name="MyProxy" transports="https,TTP,http,jms" statistics="disable" trace="disable" startOnLoad="true">
<target>
<inSequence>
<property name="OUT_ONLY" value="true"/>
<property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
<log level="full"/>
</inSequence>
<outSequence>
<drop/>
</outSequence>
<endpoint>
<address uri="jms:/MyQueue?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=tcp://localhost:61616&transport.jms.DestinationType=queue" format="pox"/>
</endpoint>
</target>
</proxy>
It is necessary to get transport headers in order to access custom JMS properties. I've found 2 ways for that:
1) from XML configuration:
<log level="custom">
<property name="jms property" expression="get-property('transport', 'custom_prop_key_1')"/>
</log>
2) from custom Class Mediator:
public boolean mediate(MessageContext synCtx) {
((Map)((Axis2MessageContext) synCtx).getAxis2MessageContext().getProperty("TRANSPORT_HEADERS")).get("custom_prop_key_1");
...
}
I do not think they are available in the SOAP message directly. They should be available in Axis2 / Transport scope. Usually JMS transport add only the JMS message's payload to SOAP body. So please try following.
Can you check them retrieving using properties in ESB and log them.
<log level="custom">
<property name="JMS_PROPERTY---->" expression="get-property('axis2','your-property-name')"/>
</log>
You can refer this on scope of properties. (If it is set at Transport headers you can change scope from 'axis2' to 'transport' and try.)
I have not personally tried this and suggesting the answer logically.
Related
I am using JMS Connector to connect to IBM MQ. If I use IBM MQ Connector I have option (targetClient="NO_JMS_COMPLIANT") to disable RFH Header from the message. How can I achieve the same thing using the JMS Connector. My JMS config looks like below
<jms:config name="JMS_Config" doc:name="JMS Config" doc:id="b675becf-06f3-4847-bb95-4f468d5353ea" >
<jms:generic-connection specification="JMS_2_0" connectionFactory="WMQ_ConnectionFactory" />
</jms:config>
Connection Factory looks like this:
<bean id="WMQ_ConnectionFactory" class="com.ibm.mq.jms.MQConnectionFactory" name="WMQ_ConnectionFactory">
<property name="transportType" value="1" />
<property name="hostName" value="MQ-SLQ01"/>
<property name="port" value="1414"/>
<property name="queueManager" value="SLQ01"/>
<property name="channel" value="*******"/>
</bean>
JMS Connector config looks like this:
<jms:publish-consume doc:name="Publish consume" doc:id="b1d40cc6-deb0-42f0-aa50-4b230d843794" config-ref="JMS_Config" destination="P2.REQUEST" sendCorrelationId="ALWAYS">
<jms:message >
<jms:reply-to destination="P2.REPLY" />
</jms:message>
</jms:publish-consume>
I have tried adding request queue name with P2.REQUEST?targetClient=1. I could not see any changes.
I doubt the JMS connector allows to select a non-JMS compatible mode that is specific to a broker (IBM MQ). It a generic connector which provides no broker specific features. You should be using the IBM MQ connector for that that already provides that specific feature.
And alternate action you could take would be to disable the RFH2 header by using a setting on the queue.
ALTER QLOCAL(P2.REQUEST) PROPCTL(NONE)
This will strip all properties (RFH2 header) off the message before delivering it to any application that doesn't supply a message handle.
We have used Camel for routing between different destination using Spring with EMS messaging:
EMS Queues/TOpics hosted on tcp/http protocol working fine, whereease SSL causes following exception:
Error: Error occured while reading identity data: failed to decrypt safe contents entry: javax.crypto.BadPaddingException: Given final block not properly padded: url that returned this exceptio= ssl://random.host.com:41943
For normal spring tibco EMS SSL connection we need to set following by overriding ListenerContainer:
TibjmsSSL.setPassword(passwordCharArray);
How can we do with camel configuration:
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="userCredentialsConnectionFactory" />
<property name="transacted" value="false" />
<property name="concurrentConsumers" value="1" />
</property>
</bean>
This is my camel jms config
I tried overriding following with my own custom implementation by setting below property, it doesnt seem to override required functionality:
org.apache.camel.component.jms.JmsConfiguration.messageListenerContainerFactory
[Fixed]
Overrided doCreateConnection(String,String) method of import org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter
and set required password in TibjmsSSL.setPassword(passwordCharArray)
I was able to create a Synchronous service bus using the JMS, but I was not able to turn it to Asynchronous.
I'm trying to post a request to a service asynchronously, so if the service is down, I want the JMS queue keeps the request message and when the service starts up it delivers the message to the service and get back the response.
here is my code
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route >
<from id ="server" uri="jetty:http://0.0.0.0:9500/rsb/toService?matchOnUriPrefix=true&enableMultipartFilter=false&disableStreamCache=false"/>
<wireTap uri="log:test?level=INFO"><body><simple>Enter JMS test route and sending message to queue</simple></body></wireTap>
<!--<to uri="direct:queue"/>-->
<to uri="jms://testqueue?requestTimeout=360000&replyTo=bar&replyToDeliveryPersistent=true&exchangePattern=InOut&acknowledgementModeName=AUTO_ACKNOWLEDGE"/>
</route>
<route id="testqueuelistener" streamCache="true">
<from uri="jms://testqueue?replyToDeliveryPersistent=true&replyTo=bar" />
<wireTap uri="log:test?level=INFO"><body><simple>Message recieved from queue: ${body}</simple></body></wireTap>
<to uri="http://localhost:18402/Home/addUser?bridgeEndpoint=true&throwExceptionOnFailure=false"/>
<to uri="jms:service"/>
</route>
<route >
<from uri="jms:service"/>
<transform>
<simple>${body}</simple>
</transform>
</route>
</camelContext>
The issue is that you are accessing the JMS queue without using a transaction - so as soon as you get the message, it's gone from the queue. You need to use a transaction and only commit (or rollback) the message consumption after you've finished processing it.
The relevant Enterprise Integration Pattern is the transactional client. The JMS component documentation also provides some information about transaction. Finally, chapter 9 of Camel in Action (chapter 12 for the second edition) is dedicated to transactions (and I can't recommend it enough!).
You need to:
Obtain a JMS transaction manager (which transaction manager you use may depend on your specific use case)
Configure the Camel JMS component to use the transaction manager
Use a transaction policy to configure the transactional behavior of your route (or just mark the route as transacted, and use the default policy)
The configuration can look something like:
<!-- Import JMS connection factory -->
<osgi:reference id="jmsConnectionPool" interface="javax.jms.ConnectionFactory" />
<!-- We create a Spring JmsTransactionManager (our transaction manager could also be an
imported OSGi service, like we do for the connection factory; for example an XA transaction
manager) -->
<bean id="jmsTxManager" class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="jmsConnectionPool"/>
</bean>
<!-- We configure the JMS component to use the transaction manager-->
<bean id="jms" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="jmsConnectionPool" />
<property name="transacted" value="true"/>
<property name="transactionManager" ref="jmsTxManager"/>
</bean>
<!-- Here's an example of a transaction policy -->
<bean id="requiresNew" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
<property name="transactionManager" ref="jtaTransactionManager"/>
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRES_NEW"/>
</bean>
Here's a transacted route:
<route id="myRoute">
<from uri="jms://..." />
<transacted/>
...
</route>
And a route can use a specific transaction policy if we want:
<route id="myRoute">
<from uri="jms://..." />
<transacted ref="requiresNew" />
...
</route>
I am trying to simply host a REST service as a proxy service in WSO2 ESB. I am using Custom Proxy to do this. When I run the created proxy, I am not able to pass parameters to the proxy service at run time. How do I do this?
My REST service will be hit on a URL of format:http://ip:host/requestMapping/{name}
The parameter 'name' has to be passed from the UI through the ESB to the service through a proxy service hosted on the ESB. Can you help me with the steps to follow to make this work?
I tried using this page: http://wso2.com/library/articles/2013/12/restful-integration-with-wso2-esb/
But that is for creating APIs which I have been successfully in creating. But I am unable to do this using Proxy services.
Basically in my program, when the user interacts with the UI, he enters a name as input. This name has to be passed to the proxy service hosted in the ESB which should forward this as a path variable to my REST service.
Right now, my service body is:
<inSequence>
<send>
<endpoint>
<http method="POST" uri-template="http://ip:port/resourceMapping/{uri.var.name}"></http>
</endpoint>
</send>
</inSequence>
<outSequence>
<send></send>
</outSequence>
use the + to control encoding as this is part of the URI Template specification. try below code.
<inSequence>
<parameter name="uri.var.name" expression="YOUR EXPRESSION" />
<send>
<endpoint>
<http method="POST" uri-template="http://ip:port/resourceMapping/{+uri.var.name}"></http>
</endpoint>
</send>
</inSequence>
<outSequence>
<send></send>
</outSequence>
WSO2ESB HTTP Endpoint throws exception when using uri.var parameters in the uri-template
You can use the Header mediator to change the value of "To" header to the desired concat expression.
For example, check this link:
Defining dynamic endpoint in wso2esb
Alternatively, if you haven't yet, you can also check the answers to a similar question here: wso2-esb-dynamically-change-endpoint-address
According to this, you should set the property "uri.var.name" in advance. i.e.,
<inSequence>
<parameter name="uri.var.name" expression="" />
<send>
<endpoint>
<http method="POST" uri-template="http://ip:port/resourceMapping/{uri.var.name}"></http>
</endpoint>
</send>
</inSequence>
<outSequence>
<send></send>
</outSequence>
The expression would depend on the way the input is formatted - XML, JSON, etc. You can read more about XPath here: https://docs.wso2.com/display/ESB490/Synapse+XPath+Variables and here: http://www.w3schools.com/xsl/xpath_syntax.asp
After trying to activate priority with activemq, I was told to try using camel (see here). But I can't get it working, and I'm not even sure how it should work.
I've added the following code, in my spring configuration:
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="jms:queue:myqueue" />
<resequence>
<batch-config batchSize="200" batchTimeout="3000" allowDuplicates="true" reverse="true"/>
<header>JMSPriority</header>
<to uri="mock:result"/>
</resequence>
</route>
</camelContext>
<bean id="jmsConfig" class="org.apache.camel.component.activemq.ActiveMQConfiguration">
<property name="connectionFactory" ref="pooledConnectionFactory"/>
<property name="transacted" value="false"/>
<property name="concurrentConsumers" value="10"/>
</bean>
<bean id="activemq" class="org.apache.camel.component.activemq.ActiveMQComponent">
<property name="configuration" ref="jmsConfig"/>
</bean>
But this configuration doesn't work (nothing is ordered), and I have a few questions:
What does mock:result mean? I couldn't find it in the documentation.
How is camel supposed to re-order the queue, is it done after the messages were created, or when a message is added?
Can it be independent from the spring activemq basic configuration? (I use here the camel ActiveMQComponent)
First, a mock endpoint is for unit testing. You can use it to validate that the expected messages were received:
MockEndpoint resultEndpoint = context.resolveEndpoint("mock:result", MockEndpoint.class);
resultEndpoint.expectedMessageCount(3);
resultEndpoint.expectedBodiesReceived("firstMessageBody", "secondMessageBody", "thirdMessageBody");
resultEndpoint.message(0).header("foo").isEqualTo("bar");
Next, the resequencer is designed to order messages based on some attribute (the header "JMSPriority" in your case) and will perform this over all messages that flow through it over a given timeout period or batch size (by default, the batch size is 100 and the timeout is 1000 ms).
Long story short, you can use the resequencer to order messages (in batches) before they are sent to the queue, in between queues or in between a queue and a consumer...