camel + netty: send only if remote server is available - apache-camel

<route>
<from uri="file://inbox?move=.txt"/>
<to uri="netty:tcp://localhost:5150?encoders=#encoders&sync=false"/>
</route>
I need to send files to a remote legacy tcp server via a socket (IP and port ). this server is sometimes unavailable so :
1- I need to check if the remote tcp server(socket ) is available.
2- if not , i need wait 5 minutes.
I tried several options but none is working.
thanks

I made it worked with the following config :
<route id="step1" trace="false">
<from uri="file:/dev/tmp/datain/?sortBy=file:name;&delete=true&maxMessagesPerPoll=1" />
<convertBodyTo type="java.lang.String" />
<to uri="direct-vm:toTcp?block=true&timeout=10000" />
</route>
<route id="step2" trace="false">
<from uri="direct-vm:toTcp?block=true&timeout=10000" />
<to uri="netty4:tcp://localhost:7000?sync=true&textline=true&requestTimeout=50000&synchronous=true" />
</route>

Related

Limit netty4 tcp endpoint to a single instance

I have a mock endpoint at 8001 that will echo anything provided to it.
I have an http endpoint that will submit the end of the URL to the mock endpoint, and provide a response from the endpoint's response.
That works fine.
The challenge is, I want the http route to use only 1 tcp connection to the 8001 endpoint.
I created a worker group as explained elsewhere, and set the worker count to 1. Looking through the source code, I'm thinking this approach should work.
However, when I do this bash command:
for a in {1..5}; do curl "http://localhost:8080/upstream/REQUESTNUM$a" > $a.txt & done;
I see multiple connections to 8001. I would have expected the http endpoint requests would have to share a single pool worker, but that doesn't seem to be the case.
Perhaps I am missing something, or perhaps there is another way to accomplish my goal of using only 1 back-end tcp connection for all the http requests.
How do I accomplish it?
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext
xmlns="http://camel.apache.org/schema/spring">
<route id="mockUpstream">
<from
uri="netty4:tcp://localhost:8001?sync=true&textline=true&keepAlive=true&disconnect=false&reuseChannel=true" />
<log message="Incoming to upstream: ${body}" />
<transform>
<simple>${body}</simple>
</transform>
</route>
<route id="httpServer">
<from
uri="netty4-http:http://0.0.0.0:8080/upstream?matchOnUriPrefix=true" />
<!-- optional just use CamelHttpQuery from header, for full query -->
<log
message="Incoming http command: ${in.headers[CamelHttpPath]}" />
<transform>
<simple>${in.headers[CamelHttpPath]}</simple>
</transform>
<to
uri="netty4:tcp://localhost:8001?workerGroup=#sharedPool&sync=true&textline=true&keepAlive=true&disconnect=false&reuseChannel=true" />
<transform>
<simple>${body}</simple>
</transform>
</route>
</camelContext>
<bean id="poolBuilder"
class="org.apache.camel.component.netty4.NettyWorkerPoolBuilder">
<property name="workerCount" value="1" />
</bean>
<bean id="sharedPool" class="io.netty.channel.EventLoopGroup"
factory-bean="poolBuilder" factory-method="build"
destroy-method="shutdown">
</bean>
</beans>
Looking at the logs, with TRACE level logging, I saw the NettyProducer's pool was indeed set to use 1 max active connection, but the NettyProducer was allowed 100 idle connections. I changed the following line and it is now behaving as expected:
<to
uri="netty4:tcp://localhost:8001?workerGroup=#sharedPool&sync=true&textline=true&keepAlive=true&disconnect=false&reuseChannel=true&producerPoolMaxActive=1&producerPoolMaxIdle=1" />
I assumed the "producer" settings were only good for the producer side (netty in mock host route) of the connection, but it looks like they can be used by the consumer end (netty in http route), too.
edit: I confused the terms producer and consumer and got that backwards above. Seeing that the "to" element is producing a request for something to consume, the producer* parameters make sense for (netty in http route). The (netty in mock host route) is the consumer of requests.

Camel-Netty4 TCP connection configuration

I'm facing connection refused exception while trying to connect through TCP even in localhost by using camel-netty4.
<route id="test-producer">
<from uri="quartz://{{t1tos.promis.containerupdate.job.detail}}" />
<to uri="bean:haSessionProcessor?method=getHAStatus" />
<log message="Server Status ::: ${body}"/>
<to uri="netty4:tcp://localhost:9001??textline=true&sync=true"/>
<log message="Server Status ::: ${body}"/>
</route>
<route id="test-consumer">
<from uri="netty4:tcp://localhost:9001clientMode=true&sync=true&textline=true"/>
<log message="Invert Server Status ::: ${body}"/>
</route>
Please advice to resolve the issue, I'm not able to find a working example for this. Do I need to configure host address and port number.

If we browse context path, Internal jaxws endpoint should not visible with context path on the browser

Thank you in advance.
Can you please give me possible solution to fix below problem.
Problem is internal jaxws endpoint should not visible on the bowser, when we browse context path(ex: http://localhost:8080/cws-finance/services).
 service name is PaymentWs. PaymentWs service has two version’s(1.1,1.2) of wsdls.
 We created two external cxf endpoints and one jaxws internal end point.
 First external endpoint interact with 1.1 version wsdl and second external endpoint interact with 1.2 version wsdl
 Internal jaxws endpoint interact with java code(serviceImpl)
 We are using camel routing to route external endpoints to internal endpoint.
 If I browse context path(ex: http://localhost:8080/cws-finance/services). I can view two are external endpoints and one is internal endpoint on the browser.
 As per requirement , internal endpoint should not view on the browser. Only two external endpoints should be visible.
 I am doing migration from service mix bundle to web application(war) deploying in tomcat. In servicemix ,it was working as per requirement. This requirement was achieved in servicemix by using NMR api with JBI container.
Internal jaxws endpoint configuration:
<jaxws:endpoint id="paymentWS" implementor="#paymentWSImp"
endpointName="tns:PaymentWSPort" address="/nmr/PaymentWS/1.2/Port"
serviceName="tns:PaymentWSService" xmlns:tns="http://www.centurytel.com/PaymentWS">
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature" />
</jaxws:features>
<jaxws:properties>
<entry key="schema-validation-enabled" value="true" />
</jaxws:properties>
</jaxws:endpoint>
External cxf endpoints configurations:
<cxf:cxfEndpoint id="paymentWS_1_1" address="/PaymentWS/1.1/Port"
endpointName="s:PaymentWSPort" serviceName="s:PaymentWSService"
wsdlURL="wsdl/paymentws_1.1.wsdl" xmlns:s="http://www.centurytel.com/PaymentWS">
<cxf:properties>
<entry key="dataFormat" value="MESSAGE" />
</cxf:properties>
</cxf:cxfEndpoint>
<cxf:cxfEndpoint id="paymentWS_1_2" address="/PaymentWS/1.2/Port"
endpointName="s:PaymentWSPort" serviceName="s:PaymentWSService"
wsdlURL="wsdl/paymentws_1.2.wsdl" xmlns:s="http://www.centurytel.com/PaymentWS">
<cxf:properties>
<entry key="dataFormat" value="MESSAGE" />
</cxf:properties>
</cxf:cxfEndpoint>
Camel routing:
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route id="paymentWS_1_1_route">
<from uri="cxf:bean:paymentWS_1_1" />
<setExchangePattern pattern="InOut" />
<convertBodyTo type="javax.xml.transform.stream.StreamSource" />
<to uri=" http://localhost:8080/cws-finance/services /nmr/PaymentWS/1.2/Port"/>
<process ref="PaymentWS_1_1_ProxyOutProc" />
<to uri="log:input" />
</route>
<route id="paymentWS_1_2_route">
<from uri="cxf:bean:paymentWS_1_2" />
<setExchangePattern pattern="InOut" />
<convertBodyTo type="javax.xml.transform.stream.StreamSource" />
<to uri=" http://localhost:8080/cws-finance/services /nmr/PaymentWS/1.2/Port"/>
<to uri="log:input" />
</route>
</camelContext>

How can I get a response from an Apache camel jetty request?

I am new to apache camel.
I want to create a service bus (middle ware) using apache camel by making a jetty Post request and then get the response from the server.
Here is what I've done
<route streamCache="true">
<from uri="jetty:{{wrapperEntry.protocol}}://{{wrapperEntry.host}}:{{wrapperEntry.port}}/rsb/SubmitNewCaseForAndroid?continuationTimeout=0" />
<convertBodyTo type="java.lang.String" />
<to uri="direct:helloworld"/>
</route>
<route streamCache="true">
<from uri="direct:helloworld"/>
<transform>
<simple>
Hello World
</simple>
</transform>
<convertBodyTo type="java.lang.String" />
</route>
the request goes successfully to the server and submit my case, other wise I cannot get the response back from the server.
Note: the response comes from the is the server is string it comes like this
'code':0,
'description':'operation completed succrssfully',
'complaintId':'45285'
Thank in Advacnce

Rename file on remote scp failure launched by Camel ssh component

When using ssh component to launch a remote scp command I must set the body. The ssh component is using the body as the command to be executed remotely.
What I want to achieve is this:
Monitor folder for files. The "from" is using delete=true as I don't want to keep files once route is completed.
Copy the file on the DMZ server using sftp.
Launch a scp on the DMZ server using ssh.
In case of failure, scp does return code greater than 0, rename the file with ".failed".
Unfortunately using ssh require that I overwrite the body and I'm loosing the content of my file. I tried to use inOnly, sending to another route, but it does not make a copy of the file but probably a copy of the file pointer. I can't use wireTap because by the time it complete the remote execution, the route is completed and the file removed. I cannot use (I think) a temporary variable because the file can be up to gigabyte in size.
I'm using Camel version 2.12.1 running under Karaf 2.3.2. I'm trying to use blueprint XML only to avoid java coding as much as possible. Below a sample. The result, in case of non-zero exit code from ssh component, is the file contain my remote command.
<route id="RemoteTest1">
<!-- 1. Monitor for incoming files -->
<from uri="file:///data/karaf/tmp/RemoteTest1/?delete=true"/>
<!-- 2. Copy file on DMZ server -->
<to uri="sftp:username#myDmz.com//home/RemoteTest1/?privateKeyFile=myPrivateKey.pk"/>
<!-- 3. Execute scp remotely -->
<setHeader headerName="remoteCommand">
<simple>scp /home/RemoteTest1/${file:name} someuser#acme.com:${file:name}</simple>
</setHeader>
<doTry>
<inOnly uri="direct-vm:remoteExec"/>
<log message="Success"/>
<doCatch>
<exception>java.lang.Exception</exception>
<!-- 4. In case of failure rename the file by adding .failed -->
<to uri="file:?fileName=${file:absolute.path}.failed"/>
<log message="Failed"/>
</doCatch>
</doTry>
</route>
<route id="remoteExec">
<from uri="direct-vm:remoteExec"/>
<setBody>
<simple>${header.remoteCommand}</simple>
</setBody>
<to uri="ssh://username#myDmz.com?certResource=file:resources/keys/myPrivateKey.pk"/>
<!-- Throw exception on remote error -->
<choice>
<when>
<simple>${header.CamelSshExitValue} != '0'</simple>
<throwException ref="remoteExecException"/>
</when>
<otherwise>
<log message="scp completed normally"/>
</otherwise>
</choice>
</route>
<bean id="remoteExecException" class="java.lang.Exception">
<argument value="Failed remote execution" />
</bean>
Is there a solution? Any help or tip would be appreciated.
Thanks

Resources