Bind Camel netty4 component to static port - apache-camel

I am newbie in Camel Netty4 component. I have a simple route:
from("direct:sendMessageToStu")
.to("netty4:udp://192.168.0.102:48000?sync=false&serverExceptionCaughtLogLevel=DEBUG");
It works properly, but I should to bind the outgoing socket's port to a static port, for example 32000. I can see the port is different in every times.
In netty, there is a simple way to fix it :
bootstrap.bind(new InetSocketAddress(32000));
But, how can I do that in Camel Netty4 component ?

Related

cannot connect to "mqtt://test.mosquitto.org" from React client

I want to connect a client React app to the mosquitto test server. The "meat" React code involved:
import mqtt from 'mqtt';
const mqttConnect = ("mqtt://192.168.1.157",{clientId:"mqttjs01"}) => {
setConnectStatus('Connecting');
console.log(mqttOptions)
setClient(mqtt.connect(host, mqttOptions));
};
The error on the web page is:
ws.js:108 WebSocket connection to 'ws://test.mosquitto.org/' failed:
so one challenge I see is the insistence of a web socket. (ws protocol). Then another challenge is my ultimate goal is to talk to a mosquitto broker running on a Raspberry Pi (port 1883, which I thought the mqqt:// was addressing). The Raspberry Pi is not using websockets.
It appears clear to me that I am clueless. Any guidance / pointing in the right direction...greatly appreciated. Thank you.
With React you have to use WebSockets (because it effectively runs in the broswers) so your URL should start with ws:// not mqtt://.
Secondly you need to specify a port because there is no default port for MQTT over Websockets (and the WebSockets library will default to port 80)
So having checked the table of port numbers on test.mosquitto.org you should be using:
ws://test.mosquitto.org:8080/
p.s your client id's also probably need to have a lot more entropy (be random) otherwise you'll only ever have 1 connected client.
As for your local setup, you will need to configure mosquitto to listen on 2 different ports:
One for normal MQTT (default 1883)
One for MQTT over WebSockets (any port you want)
e.g. a conf file something like:
allow_anonymous true
listener 1883
listener 9001
protocol websockets
Mosquitto will share the same topic space between both listeners.

Full duplex TCP connections using Netty4 and Apache Camel

For an IoT project I am working on I am researching a next, enhanced, version of our “Socket Handler” which is over 5 years of age and has evolved in a big beast doing apart from handling socket connections with IoT devices also in thread processing that has become a real pain to manage.
For my total rewrite I am looking into Apache Camel as a routing and transformation toolkit and understand how this can help us split processing steps into micro-services, loosely coupled through message queues.
One thing that I have trouble understanding however is how I can implement the following logic “the Apache Camel way”:
An IoT device sends an initial message which contains its id, some extra headers and a message payload.
Apart from extracting the message payload and routing it to a channel, I also need to use the device Id to check a message queue, named after the device id, for any commands that have to go to the device over the same socket connection that received the initial message.
Although it seems that Netty4, which is included in Camel, can deal with synchronous duplex comms, I cannot see how the above logic can be implemented in the Camel Netty4 component. Camel Routing seems to be one way only.
Is there a correct way to do this or should I forget about using camel for this and just use Netty4 bare?
It is possible to reproduce a full duplex communication by using two Camel routes :
thanks by using reuseChannel property
As this full duplex communication will be realised thanks to two different Camel routes, sync property must be set to false.
Here the first route:
from("netty4:tcp://{{tcpAddress}}:{{tcpPort}}?decoders=#length-decoder,#string-decoder&encoders=#length-encoder,#bytearray-encoder&sync=false&reuseChannel=true") .bean("myMessageService", "receiveFromTCP").to("jms:queue:<name>")
This first route will create a TCP/IP consumer thanks to a server socket (it is also possible to use a client socket thanks to property clientMode)
As we want to reuse the just created connection, it is important to initialize decoders but also encoders that will be used later thanks to a bean (see further). This bean will be responsible of sending data by using the Channel created in this first route (Netty Channel contains a pipeline for decoding / encoding messages before receiving from / sending to TCP/IP.
Now, we want to send back some data to the parter connected to the consumer (from) endpoint of the first route. Since we are not able to do it thanks to classical producer endpoint (to), we use a bean object :
from("jsm:queue:<name>").bean("myMessageService", "sendToTCP");
Here the bean code :
public class MessageService {
private Channel openedChannel;
public void sendToTCP(final Exchange exchange) {
// opened channel will use encoders before writing on the socket already
// created in the first route
openedChannel.writeAndFlush(exchange.getIn().getBody());
}
public void receiveFromTCP(final Exchange exchange) {
// record the channel created in the first route.
this.openedChannel = exchange.getProperty(NettyConstants.NETTY_CHANNEL, Channel.class);
}
}
Of course,
the same bean instance is used in the two routes, you need to use a registry to do so :
SimpleRegistry simpleRegistry = new SimpleRegistry();
simpleRegistry.put("myMessageService", new MessageService());
Since the bean is used in two different asynchronous routes, you will have to deal with some unexected situations, by for example protecting the access of openedChannel member, or dealing with unexpected deconnexion.
This post helped me a lot to find this solution :
how-to-send-a-response-back-over-a-established-tcp-connection-in-async-mode-usin
reuseChannel property documentation
After end of camel route, exchange's body and headers will back to requester as response.

Camel restlet only binds to localhost

I have a camel restlet application. The application exposes multiple http endpoints. Lately, I updated all camel components to 2.22.1 and added some other things. While all is still running fine, the application seems to be bound only to localhost:
TCP 127.0.0.1:8082 0.0.0.0:0 ABHÖREN 7608
(netstat windows).
Could this have been caused by the update? How can I set the binding address?
As I can see in http://camel.apache.org/rest-dsl.html
you should use restConfiguration like this
restConfiguration().component("restlet").host("0.0.0.0");

netty tcp communication using load balancer(L4).how can i handle config?

As i am a novice of netty .here is my problem.
client side made of netty4 tcp communication and server module created by apache camel netty.
and in the middle of this communication,we have a load balancer L4.
this is our picture.
client and server picture
client config :10.10.10.1:8501
server config :
from (10.10.10.1:8501....
from (10.10.10.1:8502....
how can i make a client config file?
If I understood your problem, you can set your two address in your client, justo do it:
.loadBalance().roundRobin().to(ExchangePattern.InOut, "address1", "address2")
But I didn't understand about your config file, for me you are talking about properties, right?
If you are talking about properties you can take ir in your routeBuilder with a Properties, like this:
Properties property = new Properties();
property.load(new FileInputStream("YourProperties.properties"));
String propA = property.getProperty("propA");
Or set it in your blueprint/spring and get it in your route.
Here you can find more explanations about it
http://camel.apache.org/using-propertyplaceholder.html

Apache Camel for TCP based streamer

The need is to have a Camel (Mina/Netty) based TCP server running on a specific port, which allows multiple TCP clients to connect to it. The content to be streamed is available in files and the TCP server has to send each line in the text files to one of the connected clients (round robin).
Can someone help me with the outline of a camel route to achieve this?
Also it is possible to throttle the streaming speed for example 100 msg/sec per connected client?
Thanks in advance.
MK
I have done something like this. Well not quite exactly to what you want but I can make some suggestions on how to get started.
Lets use the MINA component for this route as I had some issues with the Netty component see this link Exception thrown from Apache Camel Netty Consumer When more than one client sends data. Apparently this has been fixed but as my project got cancelled I never tested it again.
So from your description this will be a text line based protocol a simple route for this would look like this in the DSL
<route>
<from uri="mina2:tcp://localhost:5555?textline=true"/>
<to uri="bean:fileProcessing"/>
</route>
This route will open a listening socket on the localhost on port 5555. The route is also setup to use a textline codec. A textline codec is essentially a line of text terminated end of line character i.e. \n. If you are going to be using some other protocol you will need to look into the following items:
ProtocolEncoder—The ProtocolEncoder handles the task of taking an input
payload and putting bytes onto the TCP channel.
ProtocolDecoder—The ProtocolDecoder interprets the custom
binary protocol message to something your application can understand.
ProtocolCodecFactory— This creates the encoder and decoder.
You could implement some logic in the fileProcessing bean to send the replies back. There is a catch however the clients will have to request when they are ready to get a new line. From my understanding this follows a request reply scenario. However from what I have seen the route is only active when there is a message coming in from the client to the server.
There might be a way to initiate the sending from the server but you will need to experiment with that by yourself on getting it done I have not done anything like that myself.
Critical reading would be the following.
Mina Documentation
Blog Entry On Using MINA
My suggestion is to start with a basic route like this and then expand your logic and then come back with problems you might encounter.
UPDATE:
So I did a little research on this and it does not appear possible to send events from the server to the client without following one of the following patterns InOnly and InOut.
Try just using MINA or Netty then.

Resources