I'm struggleing while using the Apache Camel Netty Component. I want connect to a different system using a minimal route like this:
from("netty:tcp://localhost:4314?clientMode=true")
.log("${body}")
.end();
My Problem is, that in order to receive any data I have to send some subscription message using the same connection.
A similar Problem was easy to solve, when the connection was made via ActiveMQ, where you could take the connection Factory and make a seperate connection for the subscription.
I have found this Question: How to send a response back over a established TCP connection in async mode using Apache Camel Netty4?
but it only work if you can receive something before you can reply.
How can I send data, using the same Channel as the route ?
Thank you for your help !
Related
I have an application which is writing on a port(TCP message using spring-integration tcp-outbound-channel on a particular port). I want to write a listener which will listen and validate the message coming on this port.
One of the recommendation is to use socket.io. I tried to do a sample POC, But I am unable to start non http server. How can I start a socket.io based server which will listen to messages sent over TCP( without http).
I have multiple instances using Spring Boot WebSocket (created following the first half of Spring's guide). I need them to connect to other instances at specific hostnames and ports and to be able to send messages over the websocket connection using STOMP protocol.
How can I connect to my other services over websocket?
How can I send messages using the STOMP protocol (preferably using the same marshalling/unmarshalling magic I get with received messages)?
Things that don't answer my question:
I have read Spring: send message to websocket clients and Sending message to specific user on Spring Websocket but these and other questions seem to all assume that a client has already initiated a connection and that there are users and topics established. This is not my use case as my services are both server AND client.
I am not using a cluster and I am not sharing sessions across instances as in Spring Websocket in a tomcat cluster
I have found some resources that cast some light on how to accomplish this:
http://www.baeldung.com/websockets-api-java-spring-client
https://www.sitepoint.com/implementing-spring-websocket-server-and-client/#javaspringchatclient
http://useof.org/java-open-source/org.springframework.messaging.simp.stomp.StompSessionHandler
number 3 is at least a complete implementation but is unfortunately devoid of comments to explain what's going on.
I am using embedded jetty and spring for java to java communication over http. My problem is that my server application must handle plain TCP messages also on the same port.
Is there a way to detect if a TCP message arrived which cannot be handled by the servlet?
Thanks for the answers I add some more details:
I cannot modify the client. The reason for this is that the old version of the client uses pure java tcp socket and it turned out that the new server must be backward compatible with the old client.
Have to use the same port
Old client messages are short serialized text over simple socket. 1: open connection, 2: send text, 3: close connection
My server looks something like this: http://kielczewski.eu/2013/11/using-embedded-jetty-spring-mvc/
I do not need to parse the message. It is enough to detect that a message was arrived which is not using http and get the source host name.
You might want to take a look at how to add a custom ConnectionFactory to the ServerConnector of your HTTP port.
This ConnectionFactory concept is how the PROXY Protocol is supported within Jetty currently.
In your case, you might have something like ...
MyTcpConnectionFactory tcpConnectionFactory = new MyTcpConnectionFactory();
ServerConnector http = new ServerConnector(server);
http.addFirstConnectionFactory(tcpConnectionFactory);
server.addConnector(http);
In your case, you would override the newConnection(Connector connector, EndPoint endPoint) method and implement the check for your TCP flow, or the HTTP flow.
If its your flow, you handle the communications on that connection yourself and then throw an IOException when you are done indicating that you don't want jetty to process that connection as HTTP.
Otherwise you return that Connection object to Jetty to process as HTTP.
You are in for a wild ride here my friend. You need to realize that HTTP IS TCP ... its just the content being sent on the TCP socket that classifies it as HTTP or not. That being said, you can intercept the Connection with a filter ie
1) create a filter (google Java Application Server Filters and check the Jetty implementation) for ALL incoming connections
2) check for URI on the request, if it fails, then the request is not HTTP (might want to double check on the request testing logic here)
3) Redirect the request to the appropriate Servlet / Function based on serial socket / http request
On another note, why not use https (port 443) for http and port 80 for your socket requirments ?
I stand corrected. Filters wont work.
In that case, you will have to code a mini firewall. you have to scan all inputs for https headers and redirect accordingly. Can you at least provide some context on the plain TCP messages you want to receive? do you have any control over the sending code ? you do know you can upgrade a TCP/HTTP connection to a websocket (involves client and server) and it will work even better than plain TCP, same port connections, and comes built in Jetty so no custom boiler plates, just a websocket servlet
I use microservice architecture in my project. And for interservice communication I use message queue NATS. I wrote a gateway, that handle all http requests and put it to queue. All end point services are subscribed to this queue.
At endpoint services I use Xitrum based on Netty IO. When I get request from queue, I deserialise it to FullHttpRequest. But I don't know how to send it to my netty server, that can handle it according to business logic (without using external httpclient, for example, that can send it to localhost)
Is there any possibility to send FullHttpRequest instance to netty server (listening localhost:8000) using netty api? Or may be another solution. What is the common approach?
Please see the netty examples which has everything you need:
https://github.com/netty/netty/tree/4.1/example/src/main/java/io/netty/example/http/snoop
I tried to implement UDP server using Spring Integration like it's described here but when clients operate behind NAT they will never receive responses from server. It's because server should send response datagrams from the same port as UDP adapter port (check UDP via NAT explained here).
How can I achieve proper UDP communication with clients behind NAT using Spring Integration?
As discussed in those threads; there are not currently any gateways for UDP, only channel adapters. Gateways are used for two-way integration.
There has just not been any demand over the years for UDP gateways.
We did make some changes to facilitate users replying to incoming messages (by adding the sending port as as header).
This will allow you do construct a DatagramPacket (perhaps using the SI DatagramPacketMessageMapper) and send it to the originating system using your own code.
If you want us to reconsider providing UDP gateways, make a comment on the JIRA Issue. Even better, consider contributing.
EDIT
For asynchronous sends you don't need a gateway; buy you need to tweak the mapper and message handler which is built into the outbound adapter.
Change the DatagramPacketMessageMapper here to set the socketAddress using message headers; and add an option to the UnicastSendingMessageHandler so that it doesn't unconditionally set the destinationAddress here.
You can do this by subclassing the handler and overriding the send() method.
You can then wire your customized message handler into a <service-activator/> using the ref attribute.