How to pass properties in camel to different camel context's? My current architecture will process 4 different kind of messages (A,B,C,D) and it uses same routes for all of them only while saving it changes the DB table names based on message type, but now I have a requirement that I need to save only few values from the exchange object for a particular message. I'm thinking of setting a property in a route and message type is 'E' I'll direct that to another route. but how do I pass the property value to different camel context
I don't know if you mean application properties (such as in Java property files) or an Exchange property as in Camels Exchange object to wrap a message.
However, it sounds like the latter since application properties are normally not passed around.
Exchange properties are just part of the Camel wrapper around a message during processing. If you send a message during route processing to another endpoint as with .to(endpoint), normally only the message is sent and the Exchange is thrown away.
from(endpoint)
.setProperty("myProperty", value)
.to("activemq:queue:myQueue")
// myProperty is no more available at myQueue
There are of course exceptions, it depends on the endpoint type. For example when sending to direct endpoints (synchronous Camel in-memory endpoint), the Exchange survives. But direct endpoints do not work across different Camel contexts. For other endpoint types like HTTP, JMS etc the properties are lost.
Therefore, if you want to set a "message variable" that is passed to other endpoints, especially across different Camel contexts, you have to set a message header.
from(endpoint)
.setHeader("myHeader", value)
.to("activemq:queue:myQueue")
// myHeader is still available at myQueue
Related
How is window.postMessage different from window.chrome.webview.postMessage?
I'm using it in the context of a WebView2 (in a .NET/WPF application). We are loading a third-party webpage in WebView2. The webpage fires window.postMessage with certain data that we need to catch. According to the documentation, WebView2 raises WebMessageReceived event when the loaded page fires window.chrome.webview.postMessage, which is correct. On the other hand, it doesn't seem to respect window.postMessage (no WebMessageReceived is fired).
Are these two different APIs? Which one is standard (as in HTML5)? How can I catch window.postMessage event in my .NET application since I can't ask the third-party website to change their code to use window.chrome.webview.postMessage.
The chrome.webview.postMessage method is a WebView2 specific JavaScript function that allows web content to send messages to the host app via the CoreWebView2.WebMessageReceived event. It is patterned after the HTML standard window.postMessage DOM API but is different in a few ways beyond the big difference that chrome.webview.postMessage posts messages to the host app and window.postMessage posts messages to other windows:
window.postMessage(message, targetOrigin, [transfer]);
window.chrome.webview.postMessage(message);
Differences
Message parameter
They both take a message object as their first parameter to be passed by value to the target. The message is serialized by window.postMessage using the Structured Clone Algorithm (SCA) whereas window.chrome.webview.postMessage uses JSON. The largest difference between the two is SCA can handle reference cycles in the message object, whereas JSON will throw.
Origin parameter
The window.postMessage method is for posting messages to other windows and there is a risk that the window may not be on the correct origin and is not allowed to receive the message data. The origin parameter allows the caller to specify the origin that is allowed to receive the data.
In the case of WebView2 there is no such parameter as the message is being sent to the host application which is inherently trusted (its trusted since it is hosting the web content and is able to inspect the user data folder, inject script, and so on).
Transfer parameter
The optional transfer parameter to window.postMessage allows specific types of JavaScript objects to be moved to the target window. This includes things like message ports, and large arrays of data.
This scenario is not currently supported by WebView2 and likewise chrome.webview.postMessage does not have this parameter.
Forwarding to chrome.webview.postMessage
If you want to have window.postMessage messages sent to the host app, the easiest way would be to subscribe to the window.onmessage event of the target window
window.addEventListener("message", e => {
if (shouldForwardToWebView2(e)) {
window.chrome.webview.postMessage(e.data);
}
});
If you cannot subscribe to that event you could also shim the window.postMessage method:
const originalPostMessage = window.postMessage.bind(window);
window.postMessage = function (message, origin, transfer) {
if (shouldForwardToWebView2(message)) {
window.chrome.webview.postMessage(message);
}
originalPostMessage(message, origin, transfer);
};
Shimming a method like this is trickier since any errors in this shim code could break anything trying to use postMessage, unlike the event handler where failures are scoped to just that event handler.
In either case you may want to filter the messages forwarded on to WebView2 to ensure you're not sending unrelated messages from other libraries or origins you don't expect to send data to limit attack surface.
Additionally, this will only work if the messages you want to forward to WebView2 don't depend on transfer.
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.
When do I use the following syntax in Apache Camel? I have used in a sample, but don't understand the exact use of it.
exchange.setProperty("xx","xx");
exchange.getIn().setHeader("YY","YY");
exchange.getIn().setBody("ZZ")
Properties are something that related to the message itself and can be passed between routes.
Headers are often converted to/from protocol headers or affect external communication. The rule is mostly:
Metadata related to message that is used only inside routes - properties
Metadata related to some protocol (like HTTP/JMS headers etc) which is outside for routes - headers
I am new to the concepts of Camel and I would like someone to confirm my findings so far.
Please correct if wrong
The way I see it, Camel has Components, which can have several communication interfaces called Endpoints. A Component can communicate with another component by sending a message to on of its Endpoints, which then will use a Processor to deliver it to the destination. I also read about Routes but I am not sure what they are used for because they seem to overlap in function with Processors (aka, they seem to be the same thing?)
Camel Routes and Endpoints
http://java.dzone.com/articles/open-source-integration-apache
Please confirm if correct
So far I believe that a Component (C1) in machine A can use an Endpoint (E1) to communicate with another component (C2) using its endpoint (E2) in machine B, by using websockets:
http://camel.apache.org/how-do-i-configure-endpoints.html
I would be grateful if someone could enlighten me in the first question or confirm my second one. Also, is there a better way to communicate between machines that doesn't involve using webscokets?
Thanks in advance, Pedro.
A Route is what connects endpoints and processors together. When you define a route in Camel it starts with a Component that exposes a communication Endpoint, invokes processors that implement the business logic of the route, and then can output the Exchange (the message being processed) to another Endpoint that is exposed by another Component.
Certain components allow Camel routes to communicate with endpoints in different machines. For example, the JMS component can be used to communicate with other machines via JMS messages. However, some components are limited to communicating with endpoints within the same VM like the SEDA component.
Camel provides many different ways to send data between machines (Here is a list of a few of them off the top of my head):
AMQP
JMS
Amazon SQS
HTTP
Mina
Netty
Take a look at the Camel Components page for a complete list: http://camel.apache.org/components.html
First of all thanks to folks who are currently involved in the development of Camel, I am grateful for all the hard work they have put in.
I am looking for some design advice.
The architecture is something like this:
I have a bunch of Java classes which when instantiated are required to connect to each other and send messages using Apache Camel. The design constraints require me to create a framework such that all routing information, producers, consumers, endpoints etc should be a part of the camel-context.xml.
An individual should have the capability to modify such a file and completely change the existing route without having the Java code available to him.(The Java code would not be provided, only the compiled Jar would be)
For example in One setup,
Bean A ->Bean B->Bean C->file->email.
in another
Bean B->Bean A->Bean C->ftp->file->email
We have tried various approached, but if the originating bean is not implemented as a Java DSL, the messages rate is very high because camel constantly invokes Bean A in the first example and Bean B in the second(they being the source).
Bean A and Bean B originate messages and are event driven. In case the required event occurs, the beans send out a notification message.
My transformations are very simple and I do not require the power of Java DSL at all.
To summarize, I have the following questions:
1) Considering the above constraints, I do I ensure all routing information, including destination addresses, everything is a part of the camel context file?
2) Are there example I can look at for keeping the routing information completely independent of the java code?
3) How do I ensure Camel does not constantly invoke the originating bean?
4) Does Camel constantly invoke just the originating bean or any bean it sends & messages to irrespective of the position of the bean in the entire messaging queue?
I have run out of options trying various ways to set this up. Any help would be appreciated.
Read about hiding the middleware on the Camel wiki pages. This allows you to let clients use an interface to send/receive messages but totally unaware of Camel (no Camel API used at all).
Even better consider buying the Camel in Action book and read chapter 14 which talks about this.
http://www.manning.com/ibsen/
Save 41% on Manning books: Camel in Action or ActiveMQ in Action. Use code s2941. Expires 6th oct. http://www.manning.com/ibsen/
If you consider using ServiceMix of FuseESB, you might want to separate your routes in two parts.
First part would be the Event-driver bean that trigger the route. It could push messages to the ServiceNMR (see http://camel.apache.org/nmr.html).
The other part would be left to the framework users, using Spring DSL. It would just listen to message on the NMR (push by the other route) and do whatever they want with it.
Of course endpoint definition could be propertized using servicemix configuration service (see http://camel.apache.org/properties.html#Properties-UsingBlueprintpropertyplaceholderwithCamelroutes)