Sending message to Weblogic JMS Queue from a Camel Route - jms

I am trying to put a message on a Queue in Weblogic JMS, via a Camel Route.
My aim is to eventually configure a Route to consume the messages from the jms queue to which I publish the data from the earlier Route.
Here is my config:
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
<prop key="java.naming.provider.url">t3://localhost:7001</prop>
<!-- opional ... -->
<prop key="java.naming.security.principal">weblogic</prop>
<prop key="java.naming.security.credentials">weblogic</prop>
</props>
</property>
</bean>
<!-- Gets a Weblogic JMS Connection factory object from JDNI Server by jndiName-->
<bean id="webLogicJmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="jndiName" value="jms/TestConnectionFactory" /> <!-- the connection factory object is store under this name -->
</bean>
<!-- Create a new WebLogic Jms Camel Component -->
<bean id="wmq" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="webLogicJmsConnectionFactory"/>
</bean>
My Route looks like this:
from("cxfrs:bean:rsServer")
.setBody().body(TestRequest.class)
.process(new Processor(){
#Override
public void process(Exchange exchange) throws Exception {
TestRequest request = exchange.getIn().getBody(TestRequest.class);
TestResponse response = new TestResponse();
response.setAddress(request.getAddress());
response.setName(request.getName());
}
}).to("wmq:queue:TestJMSQueue");
I am getting this exception when I try to execute this Route:
May 27, 2013 6:37:47 PM org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper toResponse
WARNING: javax.ws.rs.WebApplicationException: org.springframework.jms.UncategorizedJmsException: Uncategorized exception occured during JMS processing; nested exception is weblogic.jms.common.JMSException: [JMSExceptions:045101]The destination name passed to createTopic or createQueue "TestJMSModule!TestJMSQueue" is invalid. If the destination name does not contain a "/" character then it must be the name of a distributed destination that is available in the cluster to which the client is attached. If it does contain a "/" character then the string before the "/" must be the name of a JMSServer or a ".". The string after the "/" is the name of a the desired destination. If the "./" version of the string is used then any destination with the given name on the local WLS server will be returned.
at org.apache.camel.component.cxf.jaxrs.CxfRsInvoker.returnResponse(CxfRsInvoker.java:149)
at org.apache.camel.component.cxf.jaxrs.CxfRsInvoker.asyncInvoke(CxfRsInvoker.java:104)
at org.apache.camel.component.cxf.jaxrs.CxfRsInvoker.performInvocation(CxfRsInvoker.java:57)
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96)
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:167)
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:94)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor
...
Caused by: weblogic.jms.common.JMSException: [JMSExceptions:045101]The destination name passed to createTopic or createQueue "TestJMSModule!TestJMSQueue" is invalid. If the destination name does not contain a "/" character then it must be the name of a distributed destination that is available in the cluster to which the client is attached. If it does contain a "/" character then the string before the "/" must be the name of a JMSServer or a ".". The string after the "/" is the name of a the desired destination. If the "./" version of the string is used then any destination with the given name on the local WLS server will be returned.
at weblogic.jms.frontend.FEManager.destinationCreate(FEManager.java:202)
at weblogic.jms.frontend.FEManager.invoke(FEManager.java:544)
at weblogic.messaging.dispatcher.Request.wrappedFiniteStateMachine(Request.java:961)
at weblogic.messaging.dispatcher.DispatcherImpl.syncRequest(DispatcherImpl.java:184)
at weblogic.messaging.dispatcher.DispatcherImpl.dispatchSyncNoTran(DispatcherImpl.java:287)
at weblogic.jms.dispatcher.DispatcherAdapter.dispatchSyncNoTran(DispatcherAdapter.java:59)
at weblogic.jms.client.JMSSession.createDestination(JMSSession.java:3118)
at weblogic.jms.client.JMSSession.createQueue(JMSSession.java:2514)
I followed the procedure to create a Queue mentioned here: https://blogs.oracle.com/soaproactive/entry/how_to_create_a_simple
I am creating a JMS Module(TestJMSModule) and in that I am creating a Queue(TestJMSQueue) and a connection factory inside it.
I am new to JMS and I know I am doing something wrong with the configurations either on the Camel side or the Weblogic side, but not able to figure out what. Any help would be greatly appreciated.
Thanks in advance.

You need to create a JMS Server. Then you need to create a subdeployment in your JMS Module and then target the subdeployment to the JMS Server.
Then the syntax needs to be
JMSServer/JMSModule!Queue

Unfortunately I'm not an expert in WebLogic configuration.
Client side config looks correct.
The exception says the object name is not right.
In the example you mentioned jndi name of the queue is "jms/TestJMSQueue", not just "TestJMSQueue".
To me it means you should be using .to("wmq:queue:jms/TestJMSQueue"); instead.

I was to integrate Spring (4.1.6) + Apache Camel (2.15.2) and consuming messages from a JMS Queue hosted on Oracle Weblogic (11g).
applicationContext.xml
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
<prop key="java.naming.provider.url">t3://localhost:7001</prop>
<prop key="java.naming.security.principal">weblogic</prop>
<prop key="java.naming.security.credentials">welcome1</prop>
</props>
</property>
</bean>
<bean id="webLogicJmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplate" />
<!-- Connection factory JNDI name -->
<property name="jndiName" value="jms/TestConnectionFactory" />
</bean>
<bean id="weblogicJmsComponent" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="webLogicJmsConnectionFactory" />
</bean>
<camel:camelContext id="camel" xmlns:camel="http://camel.apache.org/schema/spring">
<!-- Route to copy files -->
<camel:route startupOrder="1">
<camel:from uri="file:data/inbox?noop=true" />
<camel:process ref="loggingProcessor" />
<camel:to uri="file:data/outbox" />
</camel:route>
<!-- Route to read from JMS and process them in jmsReaderProcessor -->
<camel:route startupOrder="2">
<camel:from uri="weblogicJmsComponent:queue:TestJMSServer/TestJMSModule!TestJMSQueue" />
<camel:process ref="jmsReaderProcessor" />
</camel:route>
</camel:camelContext>
loggingProcessor and jmsReaderProcessor are two Camel Processor that just log the messages in/out from Exchange object.
public void process(Exchange exchange) throws Exception {
LOG.info("begin process()");
LOG.info("process() -- Got exchange: {}", exchange);
Message messageIn = exchange.getIn();
LOG.info("process() -- Got messageIn: {}", messageIn);
LOG.info("process() -- Got messageIn.getBody(): {}", messageIn.getBody());
Message messageOut = exchange.getOut();
LOG.info("process() -- Got messageOut: {}", messageOut);
LOG.info("end process()");
}
Kind Regards,
Cristian Manoliu

Related

Spring SAML: SAML message intended destination endpoint did not match recipient endpoint

I am getting 'Caused by: org.opensaml.xml.security.SecurityException: SAML message intended destination endpoint did not match recipient endpoint' exception while SSO between my app SP and client IdP.
Server log show the difference in schemas, see below:
Checking SAML message intended destination endpoint against receiver endpoint
2019-03-05 15:02:44.599 DEBUG [204 default task-41][BaseSAMLMessageDecoder] Intended message destination endpoint: https://my.app.com/app-gateway/saml/SSO
2019-03-05 15:02:44.599 DEBUG [204 default task-41][BaseSAMLMessageDecoder] Actual message receiver endpoint: http://my.app.com/app-gateway/saml/SSO
2019-03-05 15:02:44.600 ERROR [204 default task-41][BaseSAMLMessageDecoder] SAML message intended destination endpoint 'https://my.app.com/app-gateway/saml/SSO' did not match the recipient endpoint 'http://my.app.com/app-gateway/saml/SSO'
My application is running on STG on 2 instances with the LB in front, therefore I use SAMLContextProviderLB context provider instead of SAMLContextProviderImpl:
<bean id="contextProvider" class="org.springframework.security.saml.context.SAMLContextProviderLB">
<property name="scheme" value="https"/>
<property name="serverName" value="my.app.com"/>
<property name="serverPort" value="443"/>
<property name="includeServerPortInRequestURL" value="false"/>
<property name="contextPath" value="/app-gateway"/>
</bean>
<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<property name="entityBaseURL" value="https://my.app.com/app-gateway1"/>
<property name="entityId" value="${cas.sso.entityId}"/>
<property name="includeDiscoveryExtension" value="false"/>
<property name="extendedMetadata" ref="extendedMetadata"/>
<property name="keyManager" ref="keyManager"/>
</bean>
</constructor-arg>
</bean>
In the source code of getActualReceiverEndpointURI the receiver endpoint URL is being taken from request httpRequest obj. Thus, I am trying to understand at which step that wrong URL http://my.app.com/app-gateway/saml/SSO was set to it. Can anyone explain me it?
protected String getActualReceiverEndpointURI(SAMLMessageContext messageContext) throws MessageDecodingException {
InTransport inTransport = messageContext.getInboundMessageTransport();
if (! (inTransport instanceof HttpServletRequestAdapter)) {
log.error("Message context InTransport instance was an unsupported type: {}",
inTransport.getClass().getName());
throw new MessageDecodingException("Message context InTransport instance was an unsupported type");
}
HttpServletRequest httpRequest = ((HttpServletRequestAdapter)inTransport).getWrappedRequest();
StringBuffer urlBuilder = httpRequest.getRequestURL();
return urlBuilder.toString();
}
You might want to check the following page :
https://developer.jboss.org/thread/240113
I had a similar issue, even with X-Forwarded-Proto properly set on the LB, the request was still interpreted in http only.
The backend must be aware of the header.
add proxy-address-forwarding="true" on the http listener and two filter-ref
<http-listener name="default" socket-binding="http" proxy-address-forwarding="true"/>
<filter-ref name="server-header"/>
<filter-ref name="x-powered-by-header"/>
Hope this help,
For Apache Tomcat server, which is running behind AWS Application load balancer, need to enable the RemoteIPValue so that based on the x-forwarded-proto header, Tomcat will overwrite scheme(https) & port(443) accordingly.
In server.xml
<Valve className="org.apache.catalina.valves.RemoteIpValve" protocolHeader="X-Forwarded-Proto" internalProxies="10\.\d+\.\d+\.\d+|192\.168\.\d+\.\d+|169\.254\.\d+\.\d+|127\.\d+\.\d+\.\d+|172\.(1[6-9]|2[0-9]|3[0-1])\.\d+\.\d+" />

spring DefaultMessageListenerContainer and websphere MQ - failed to connect Queue Manager

This is my first time to post question on stackoverflow. I tried as much formatting for code/question and try to as much clear as i can do. apologize and explain if there's any err. recorrect in my next question.
I am newbie in try implementing service through soap over jms using websphereMq and spring JMS functionality.
I have make sure below things
binding file generated without any error encounter
Status of queue manager and Queue are up and running.
I encounter below error while try putting message into websphereMQ
com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2058' ('MQRC_Q_MGR_NAME_ERROR')
I have done homework regarding this error. This error may occurs due to unavailability of Queue manager but i see QM is up and running. where i am doing wrong? How can i resolved this error to put message successfully to webspherMQ using spring functionlity?
TestClass
public class JmsTransportWebServiceIntegrationTest {
private static final String expectedResponseContent = "<tns:placeOrderResponse xmlns:tns=\"http://www.packtpub.com/liverestaurant/OrderService/schema\"><tns:refNumber>order-xxxx_yyyy_1234</tns:refNumber></tns:placeOrderResponse>";
#Autowired
private WebServiceTemplate webServiceTemplate;
public void setWebServiceTemplate(WebServiceTemplate webServiceTemplate) {
this.webServiceTemplate = webServiceTemplate;
}
#Test
public void testSendReceive() throws Exception {
InputStream is = new JmsTransportWebServiceIntegrationTest().getClass().getResourceAsStream("placeOrderRequest.xml");
StreamSource source = new StreamSource(is);
StringResult result = new StringResult();
webServiceTemplate.sendSourceAndReceiveToResult(source, result);
XMLAssert.assertXMLEqual("Invalid content received", expectedResponseContent, result.toString());
} }
applicationContext.xml
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<map>
<entry key="java.naming.factory.initial"
value="com.sun.jndi.fscontext.RefFSContextFactory"/>
<entry key="java.naming.provider.url" value="file:C:/JNDI-Directory" />
</map>
</property>
</bean>
<bean id="ibm-mq-jms-qcf" class= "org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate"/>
</property>
<property name="jndiName">
<value>jms/mdpSampleQCF</value>
</property>
</bean>
<!-- Bean for JMS Destination -->
<bean id="ibm-mq-queue" class= "org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate"/>
</property>
<property name="jndiName">
<value>jms/mdpSampleQueue</value>
</property>
</bean>
<bean id="listenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="1" />
<property name="connectionFactory" ref="ibm-mq-jms-qcf" />
<property name="destination" ref="ibm-mq-queue" />
<property name="messageListener">
<bean class="org.springframework.ws.transport.jms.WebServiceMessageListener">
<property name="messageFactory" ref="messageFactory"/>
<property name="messageReceiver" ref="messageDispatcher"/>
</bean>
</property>
</bean>
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory"/>
<property name="messageSender">
<bean class="org.springframework.ws.transport.jms.JmsMessageSender">
<property name="connectionFactory" ref="ibm-mq-jms-qcf"/>
</bean>
</property>
<property name="defaultUri" value="jms:mdpSampleQueue?deliveryMode=NON_PERSISTENT"/>
</bean>
<bean id="messageDispatcher" class="org.springframework.ws.soap.server.SoapMessageDispatcher">
<property name="endpointMappings">
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
<property name="defaultEndpoint">
<bean class="com.packtpub.liverestaurant.service.endpoint.SimplePayloadEndpoint">
<property name="orderService">
<bean class="com.packtpub.liverestaurant.service.OrderServiceImpl"/>
</property>
</bean>
</property>
</bean>
</property>
</bean
I know this is quite old question, but maybe my answer will help someone in future.
I'm using WebSphere MQ 7.5 now and in installation there are also some Java classes. One that helped me a lot is called MQIVP.java in my installation in c:\Program Files (x86)\IBM\WebSphere MQ\tools\wmqjava\samples. Very good to test setting with this class first. From source of that class we can find that 2058 stands for:
Reason: 2058 - Queue manager name not valid or not known.
Action: Amend the queue manager name and retry.
Simply pressing enter at the queue manager name prompt will
connect to the default queue manager.

Is it possible to read a combination of a System Property and a Customized Property in Spring config file?

I need to know if its possible in Spring to derive a value for a Property by combination of a System-Property and a Customized-Property defined over a PropertyFile.
What I've done:
1) Configured a -D argument in server as : -Dapp.Env="dev"
2) In my spring-config.xml, defined datasource details as below:
<!-- DataSource configurations -->
<bean id="myDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="myDataSource" />
<property name="xaDataSourceClassName" value="${my.database.xaDriver.class}" />
<property name="xaProperties">
<props>
<prop key="URL">#{systemProperties['appEnv']}.${my.database.jdbcUrl}</prop>
<prop key="user">#{systemProperties['appEnv']}.${my.database.user}</prop>
<prop key="password">#{systemProperties['appEnv']}.${my.database.password}</prop>
</props>
</property>
<property name="maxPoolSize" value="${my.database.maxPoolSize}" />
<property name="minPoolSize" value="${my.database.minPoolSize}" />
<property name="borrowConnectionTimeout" value="60" />
<property name="maintenanceInterval" value="120" />
</bean>
3) Defined the following properties in my .properties file:
my.database.xaDriver.class=oracle.jdbc.xa.client.OracleXADataSource
my.database.initialPoolSize=2
my.database.maxPoolSize=10
my.database.minPoolSize=2
dev.my.database.jdbcUrl=jdbc:oracle:thin:#test.com:1535:myDb
dev.my.database.user=myuserid
dev.my.database.password=mypwd
4) Defined .properties file location in the spring-config.xml as :
<context:property-placeholder location="/WEB-INF/spring/spring-config.properties" />
What I get on start of server :
Throwable occurred: org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'myDataSource' defined in ServletContext resource [/WEB-INF/spring/spring-config.xml]: Could not resolve placeholder 'my.database.jdbcUrl' in string value "#{systemProperties['appEnv']}.${my.database.jdbcUrl}"
What I also tried :
5) Defined a property in .properties file as below:
app.Env=dev
6) Modified the datasource bean configuration as below:
<prop key="URL">${app.Env}.${my.database.jdbcUrl}</prop>
<prop key="user">${app.Env}.${my.database.user}</prop>
<prop key="password">${app.Env}.${my.database.password}</prop>
However on start of server, I get same exception message :
Throwable occurred: org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'myDataSource' defined in ServletContext resource [/WEB-INF/spring/spring-config.xml]: Could not resolve placeholder 'my.database.jdbcUrl' in string value "${app.Env}.${my.database.jdbcUrl}"
Can someone help me out in pointing out what mistake I might be doing and what is/are the possible fix for this issue ?
1) You can read system properties into Spring bean:
<bean id="systemProperties" class="java.lang.System" factory-method="getProperties"/>
and then use multiple property resolvers
2) You can use flag systemPropertiesMode of PropertyPlaceholderConfigurer
3) You can write your custom bean factory that would produce single java.util.Properties object from system properties and file properties.
That bean would have method
public Properties merge() {
Properties merged = new Properties();
for (Properties p : properties) {
if (p != null) {
merged.putAll(p);
}
}
return merged;
}
Invoked in spring like that:
<bean id="factory" class="my.Factory">
<property name="properties">
<util:list>
<bean class="java.lang.System" factory-method="getProperties"/>
<bean ref="otherProperties">
</util:list>
</property>
</bean>

Spring-JMS(Websphere MQ)

I have the below configurations in Spring , it is working fine but performance is too low (it takes 1 min for 20 messages). Can you please suggest me changes to increase the performance.
<bean id="jmsConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="transportType"><value>1</value></property>
<property name="queueManager"><value></value></property>
<property name="hostName"><value></value></property>
<property name="port"><value></value></property>
<property name="channel"><value></value></property>
<property name="clientId"><value></value></property>
</bean>
<bean id="SenderJMSTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory"><ref bean="jmsConnectionFactory" /> </property>
<property name="pubSubDomain"><value>false</value></property>
<property name="defaultDestination"><ref bean="senderQueue" /></property>
</bean>
<bean id="senderQueue" class="com.ibm.mq.jms.MQQueue">
<constructor-arg value="TEST" />
<property name="baseQueueManagerName"><value>tree.queue.manager</value></property>
<property name="baseQueueName"><value>ORANGE.QUEUE</value></property>
</bean>
<bean id="jmsSender" class="org.tree.jms.spring.JMSSender">
<property name="jmsTemplate"><ref bean="SenderJMSTemplate"/></property>
</bean>
I am calling from spring as
JMSSender obj = (JMSSender) context.getBean("jmsSender");
And My Sender program is :
#Cacheable("message")
public void sendMesage() {
jmsTemplate.send(new MessageCreator() {
public Message createMessage(Session session)throws JMSException {
message = (Message) session.createTextMessage(stringBuffer.toString());
return message;
}
});
}
}
A common problem when using JMSTemplate to send messages out of JavaEE containers is the it's extremly slow since it acquires a new connection for each message (and then closes it). You would probably need a pooled/cached connection to gain speed here.
Read this article, it's written for ActiveMQ, but applies in a similar way to WebSphere MQ: http://activemq.apache.org/jmstemplate-gotchas.html
You can setup a cached connection factory in spring using something like this:
<bean id="cachedConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory"
p:targetConnectionFactory-ref="jmsConnectionFactory"
p:sessionCacheSize="10" />
Then use it instead of the original one for JMS connections.

JMS implementation using JNDI in spring application

I am trying to implement JMS in my spring application. I have defined the JNDI name + queue name in applicationContext.xml as follows:
<bean id="emailQueueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="true">
<property name="jndiName" value="java:comp/env/jms/<<Name of JNDI of connection factory>>" />
</bean>
<bean id="emailQueueDestination" class="org.springframework`enter code here`.jndi.JndiObjectFactoryBean" lazy-init="true">
<property name="jndiName" value="java:comp/env/jms/<<JNDI name of queue>>" />
</bean>
<bean id="emailQueueTemplate" class="org.springframework.jms.core.JmsTemplate" lazy-init="true">
<property name="connectionFactory" ref="emailQueueConnectionFactory" />
<property name="defaultDestination" ref="emailQueueDestination" />
</bean>
<bean id="emailSender" class="<<Package>>.EmailSender" lazy-init="true">
<property name="jmsTemplate">
<ref bean="emailQueueTemplate" />
</property>
</bean>
Now my controller makes a call to the emailSender bean using the following code:
ApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
EmailSender sender =(EmailSender)context.getBean("emailSender");
The exception I get is: Error 404: Request processing failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [applicationContext.xml]; nested exception is java.io.FileNotFoundException: class path resource [applicationContext.xml] cannot be opened because it does not exist
I am loading the applicationContext.xml at serevr start-up still my code is not able to locate this file.
Can anyone please help.??
make sure your applicationContext.xml file is in your class path then add the class path prefix, You can try some thing like this
ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:applicationContext.xml");

Resources