currently I am working with camel and wmq. What I tried to do is sending a message to wmq. I configure the camel by using Spring Framework. Here is how configure the wmq:
component.xml
<bean id="websphere-mq" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory">
<bean class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="transportType">
<util:constant static-field="com.ibm.mq.jms.JMSC.MQJMS_TP_CLIENT_MQ_TCPIP" />
</property>
<property name="hostName" value="localhost" />
<property name="port" value="1414" />
<property name="queueManager" value="localmanager" />
<property name="channel" value="CH.ADM1" />
<property name="CCSID" value="819"/>
<property name="useConnectionPooling" value="true" />
</bean>
</property>
</bean>
config.xml
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="stream:in?promptMessage=Ausweisnummer: "/>
<process ref="TransformToXML"/>
<to uri ="xslt:mobako.sender.xsl"/>
<to uri ="websphere-mq:queue:LSMH.ZKSEAP.SERVICEBUS"/>
</route>
<route>
<from uri="websphere-mq:queue:ZKSEAP.LSMH.SERVICEBUS"/>
<to uri="stream:out"/>
</route>
</camelContext>
When I check the to the wmq, I found out that the wmq has been listening to my process, but it did not get any message.
Then to check if my wmq configuration is right, I tried to change my config.xml into something like this:
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="websphere-mq:queue:ZKSEAP.LSMH.SERVICEBUS"/>
<to uri="stream:out"/>
</route>
</camelContext>
After that I tried to write the message manually to the wmq. And when I tried to run my process, then the message from wmq is writen on my console.
Then, I sum up that, with my configuration, I can get the message from the wmq, but I can not write to wmq.
What is the problem actually? Is there something wrong or missing from my configuration? Thanks so much.
EDITED
Hey, finally I found out what is wrong.
The problem is: my jms version not the same with my camel version.
But, after I changed the jms version, I got following error (regarding to the wmq) on my server:
2014-06-05 15:14:34,859 [Axis2 Task] ERROR WMQMsg - Expected MQ message format '
MQSTR ', but received 'MQHRF2 '
How to solve it? Thanks again.
I think your problem is in your JMS message types and conversion.
Please see following link and try to convert your message type that you get from stream:in.
http://www-01.ibm.com/support/knowledgecenter/SSFKSJ_7.0.1/com.ibm.mq.csqzaw.doc/jm25524_.htm?cp=SSFKSJ_7.0.1%2F1-25-3-4-1-1-1&lang=en
http://www.capitalware.com/rl_blog/?p=1168
Processing MQ ByteMessage using JMS client
Firstly, I don't really understand your route:
Specifically, you have two .to uris. Maybe I am wrong, but logically you'd need some kind of logic to route a message to one endpoint or another.
Secondly, if I may, I will provide you with a solution that worked for me.
As I understood, you only need to set up a camel endpoint of type jms, and then let the camel do all the boilerplate code for you. You do require a specific ConnectionFactory (in our case wmq). I will create it in Java, doing it with Spring beans just adds complexity.
CamelContext camelContext = new DefaultCamelContext();
MQQueueConnectionFactory connectionFactory = new MQQueueConnectionFactory();
connectionFactory.setHostName("localhost");
try {
connectionFactory.setPort(1414);
connectionFactory.setQueueManager("QueueManagerName");
connectionFactory.setChannel("ChannelName");
connectionFactory.setTransportType(1);
} catch (JMSException e) {
e.printStackTrace();
}
camelContext.addComponent("wmq", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
For the second part, we can use the wmq as any other endpoint.
try {
camelContext.addRoutes(new RouteBuilder() {
#Override
public void configure() throws Exception {
from("file://data/in/?noop=true")
.to("wmq:queue:YourQueueName");
}
});
} catch (Exception e) {
e.printStackTrace();
}
Related
I have some problem. I need to take the route or all CamelContext from blueprint file. How can i did it?
route.xml
I have tried to add route via RouteDefinitions but it throws exceptions because it expected spring namespace but i use blueprint namespace. I use cxf as implementation of JAX-RS. There is another way how to do it better.
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
<bean id="weatherMailService" class="com.test.mail.MailSenderImpl"/>
<service ref="weatherMailService" interface="com.test.mail.MailSender"/>
<bean id="serviceProcessor" class="com.test.mail.MailSenderImpl"/>
<bean id="context" class="com.test.mail.MailSenderImpl"></bean>
<camelContext id="ctx" xmlns="http://camel.apache.org/schema/blueprint">
<route id="mail">
<from uri="direct:start"/>
<setBody>
<constant>Test</constant>
</setBody>
<setHeader headerName="subject">
<simple>Weather</simple>
</setHeader>
<process ref="serviceProcessor"/>
<to uri="smtps://smtp.gmail.com:465?username=RAW(*****#gmail.com)&password=******&to=******#gmail.com"/>
<to uri="log:start"/>
<process ref="context"></process>
</route>
</camelContext>
I would like to get CamelContext in java code. How can i did it? Thank you
Spring integration tcp gateway can be setup as follows:
<!-- Server side -->
<int-ip:tcp-connection-factory id="crLfServer"
type="server"
port="${availableServerSocket}"/>
<int-ip:tcp-inbound-gateway id="gatewayCrLf"
connection-factory="crLfServer"
request-channel="serverBytes2StringChannel"
error-channel="errorChannel"
reply-timeout="10000" />
<int:channel id="toSA" />
<int:service-activator input-channel="toSA"
ref="echoService"
method="test"/>
<bean id="echoService"
class="org.springframework.integration.samples.tcpclientserver.EchoService" />
<int:object-to-string-transformer id="serverBytes2String"
input-channel="serverBytes2StringChannel"
output-channel="toSA"/>
<int:transformer id="errorHandler"
input-channel="errorChannel"
expression="Error processing payload"/>
Notice the reply-timeout which is set as 10 seconds.
Does it mean that the TCP server will call the service and can wait for a maximum of 10 seconds? If the service does not reply within 10 seconds, Does the TCP server will send the message to errorChannel which in turn sends the client error message "Error processing payload"?
When I tested the TCP Server with a service that takes 20 seconds, client is taking 20 seconds to get the response. I am not seeing error message.
Can you please help in understanding the reply-timeout in TCP inbound-gateway?
Thanks
UPDATE:
Thanks for Artem to help out with this issue.
Best way to solve this problem is with the following config:
<beans>
<int-ip:tcp-connection-factory id="crLfServer" type="server" port="${availableServerSocket}"/>
<int-ip:tcp-inbound-gateway id="gatewayCrLf" connection-factory="crLfServer" request-channel="requestChannel" error-channel="errorChannel" reply-timeout="5000" />
<int:service-activator input-channel="requestChannel" ref="gateway" requires-reply="true"/>
<int:gateway id="gateway" default-request-channel="timeoutChannel" default-reply-timeout="5000" />
<int:object-to-string-transformer id="serverBytes2String" input-channel="timeoutChannel" output-channel="serviceChannel"/>
<int:channel id="timeoutChannel">
<int:dispatcher task-executor="executor"/>
</int:channel>
<bean id="executor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="maxPoolSize" value="10" />
<property name="queueCapacity" value="25" />
</bean>
<int:service-activator input-channel="serviceChannel" ref="echoService" method="test"/>
<bean id="echoService" class="org.springframework.integration.samples.tcpclientserver.EchoService" />
<int:transformer id="errorHandler" input-channel="errorChannel" expression="payload.failedMessage.payload + ' errorHandleMsg: may be timeout error'"/>
</beans>
Thanks
Well, actually we should on that attribute a description like we have in other similar places, e.g. HTTP Inbound Gateway:
<xsd:attribute name="reply-timeout" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Used to set the receiveTimeout on the underlying MessagingTemplate instance
(org.springframework.integration.core.MessagingTemplate) for receiving messages
from the reply channel. If not specified this property will default to "1000"
(1 second).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
That timeout means how much to wait for reply from downstream flow. But! That is possible if you flow is shifted to another thread somewhere. Otherwise everything is performed in the caller's Thread and therefore the wait time isn't deterministic.
Anyway we return null there after timeout without reply. And it is reflected in the TcpInboundGateway:
Message<?> reply = this.sendAndReceiveMessage(message);
if (reply == null) {
if (logger.isDebugEnabled()) {
logger.debug("null reply received for " + message + " nothing to send");
}
return false;
}
We can reconsider a logic in the TcpInboundGateway for :
if (reply == null && this.errorOnTimeout) {
if (object instanceof Message) {
error = new MessageTimeoutException((Message<?>) object, "No reply received within timeout");
}
else {
error = new MessageTimeoutException("No reply received within timeout");
}
}
But seems for me it really would be better on to rely on the timeout from the client.
UPDATE
I think we can overcome the limitation and meet you requirements with the midflow <gateway>:
<gateway id="gateway" default-request-channel="timeoutChannel" default-reply-timeout="10000"/>
<channel id="timeoutChannel">
<dispatcher task-executor="executor"/>
</channel>
<service-activator input-channel="requestChannel"
ref="gateway"
requires-reply="true"/>
So, the <service-activator> calls <gateway> and waits for reply from there. Requiring the last one, of course, to end up with the ReplyRequiredException, which you can convert into desired MessageTimeoutException in your error flow on the error-channel="errorChannel".
The timeoutChannel is an executor one, making our default-reply-timeout="10000" very useful because we shift a message on the gateway into separate thread immediately and move right from there into reply waiting process wrapped with that timeout on the CountDonwLatch.
Hope that is clear.
I'm using apache camel File in order to read a file from the file system into a bean method. I'm using it with spring xml . I need to override prepareOnStartup method in GenericFileProcessStrategy class on the route process .
Can you please tell me what is the Syntax to do it in the from uri route line in the spring xml file ?
the spring xml :
<bean id="adoFilter" class="calypsox.bllInterfaces.cashMgn.cashMgnAdo.AdoFileFilter"/>
<camelContext xmlns="http://camel.apache.org/schema/spring" id="cashMgn">
<propertyPlaceholder id="cashMgnProperty"
location="${bll.resources.env}/cashMgn.properties" />
<route id="cashMgnAdo">
<from uri="file:{{cashMgnAdoFileDir}}?filter=#adoFilter;move=.org/${date:now:yyyyMMdd}/${file:name}&readLock=changed&readLockCheckInterval=2000&readLockTimeout=10000&moveFailed=.failed" />
<convertBodyTo type="java.lang.String" />
<to uri="bean:cashMgnHandler?method=handleCashMgnAdo" />
</route>
</camelContext>
The GenericFileProcessStrategy can be set with the processStrategy property :
<bean id="myProcessStrategy" class="..."/>
..
<from uri="file:..?..processStrategy=#myProcessStrategy"/>
I have a service bundle where I want to compress a response by using CXF GZIPFeature. The bundle is deployed on JBoss Fuse(jboss-fuse-6.1.0.redhat-379). Camel route configuraion is:
<cxf:bus id="cxf" name ="cxf">
<cxf:features>
<bean class="org.apache.cxf.transport.common.gzip.GZIPFeature">
<property name="threshold">
<value>1</value>
</property>
</bean>
</cxf:features>
</cxf:bus>
<camel:camelContext ...>
<camel:route id="test-server">
<camel:to uri="cxfbean:servicebeans?bus=#cxf&providers=#providers" />
</camel:route>
</camel:camelContext>
But this throws classcast exception:
java.lang.ClassCastException: org.apache.cxf.transport.common.gzip.GZIPOutInterceptor$GZipThresholdOutputStream cannot be cast to org.apache.cxf.io.CachedOutputStream
at org.apache.camel.component.cxf.transport.CamelDestination$CamelOutputStream.commitOutputMessage(CamelDestination.java:284)[204:org.apache.camel.camel-cxf-transport:2.12.0.redhat-610379]
at org.apache.camel.component.cxf.transport.CamelDestination$CamelOutputStream.doClose(CamelDestination.java:296)[204:org.apache.camel.camel-cxf-transport:2.12.0.redhat-610379]
at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:220)[164:org.apache.cxf.cxf-api:2.7.0.redhat-610379]
at java.util.zip.DeflaterOutputStream.close(DeflaterOutputStream.java:241)[:1.7.0_67]
at org.apache.cxf.io.AbstractWrappedOutputStream.close(AbstractWrappedOutputStream.java:77)[164:org.apache.cxf.cxf-api:2.7.0.redhat-610379]
at org.apache.cxf.io.AbstractThresholdOutputStream.close(AbstractThresholdOutputStream.java:102)[164:org.apache.cxf.cxf-api:2.7.0.redhat-610379]
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)[164:org.apache.cxf.cxf-api:2.7.0.redhat-610379]
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)[164:org.apache.cxf.cxf-api:2.7.0.redhat-610379]
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)[164:org.apache.cxf.cxf-api:2.7.0.redhat-610379]
Is there a legal way to use CXF GZIPFeature in the route? I don't want to use Camel's DataFormat to gzip.
I'm using servicemix-camel-cxf and had nearly the same problem. In the end I decided to simply add this in route:
<marshal>
<gzip/>
</marshal>
Check it out - maybe it will help you too.
But in that case you have to set Content-Type: gzip header.
Try to add
<setHeader headerName="Content-Type">
<constant>gzip</constant></setHeader>
However for me it didn't help, so I added header in java code. =)
I have the following Camel route:
<route id="myroute">
<from uri="timer://runOnce?repeatCount=1&delay=10" />
<!-- Set a new property on the exchange. -->
<to uri="bean:propSetter?method=setProp" />
<to uri="direct:fizz" />
</route>
My PropSetter bean:
public class PropSetter {
// Add new "buzz" ArrayList<Long> to the exchange.
public void setProp(Exchange exchange) {
exchange.setProperty("buzz", new ArrayList<Long>());
}
}
I would like to rewrite this without a Java bean and instead use Camel's <setProperty/> element. The only thing I can think of is to use the built-in Groovy expression:
<route id="myroute">
<from uri="timer://runOnce?repeatCount=1&delay=10" />
<!-- Set a new property on the exchange. -->
<setProperty propertyName="buzz">
<groovy>new ArrayList<Long>();</groovy>
</setProperty>
<to uri="direct:fizz" />
</route>
But this does not seem to work. So how can I use XML to set a new ArrayList<Long> on the exchange called buzz?
Define a list using Spring's util namespace as :
<util:list id="myList" value-type="java.lang.String">
</util:list>
Then using the simple language you can access the bean and set in an exchange property
<camel:setProperty propertyName="buzz">
<camel:simple>${bean:myList}</camel:simple>
</camel:setProperty>