Today we (Berthold, Chris and me) developed just for fun a websocket component for Apache Camel. “WebSocket is a technology providing for bi-directional, full-duplex communications channels, over a single Transmission Control Protocol (TCP) socket.” (Wikipedia). In combination with Apache Camel you can push events from all components (file, ftp, hazelcast, queue, etc.) to your browser. This offers you great possibilities e.g. in process tracking, process driven forms and others.
The implementation is based on the Jetty plugin (jetty-websocket). This was a simple decision, because jetty is part of Apache Camel and other projects like Apache Karaf. And last but not least – Jetty offers a websocket implementation. You can have a look at our project on github.
Okay – let’s play around :) First route is a simple in-out pattern. We send a message to camel and get it back immediately. Let’s have a look:
... from("websocket://foo") .log("${body}") .to("websocket://foo"); ... |
No magic here. For the whole test have a look at github. Yes we’ve cheated here a bit, to get a running camel instance with nearly no effort, but as I wrote above it was just for fun and a first proof of concept ;) To test the route from browser site (in our case Chrome, but Firefox 4.x should work as well) we’ve taken the demo page from Greg Wilkins blog entry about jetty and Websockets. For the test we modified line 16:
...
//var location = document.location.toString().replace('http://','ws://').replace('https://','wss://');
var location = "ws://localhost:9292/foo/"
... |
Okay. Let’s send some messages. Run the test (which runs a camel instance for 5 minutes). Open the test page in Chrome and join the chat:
If you send a message to the server, you will get it simply back. That’s good for speaking to your self but not for chatting ;) So let’s send the message to all. We’ve implemented, that if the socket correlation key is not inside the message header, the message will be send to all channel listeners (this should be later resolved over a options attribute). Here’s the route:
... from("websocket://foo") .log("${body}") .setHeader(WebsocketConstants.CONNECTION_KEY, constant(null)) .to("websocket://foo"); ... |
If you now join the chat on window one, you will get a message out printed on your own window. What’s with the second one? He has not join the chat yet :) So if he sends a message to the websocket, it will be printed on both screens. Now it’s we’re having a real chat application.
Okay. Let’s bring Camel into game. Receiving and sending a message is simple. Let’s do the communication over… the file system :) Here’re the routes:
... from("websocket://foo") .log("${body}") .to("file:/home/claus/tmp/file?doneFileName=done"); from("file:/home/claus/tmp/file") .to("websocket://foo"); ... |
The result is pretty the same as before as you can see…
…but the communication went over the file system:
I’m pretty sure it’s not the best way to send chat messages over file system, but it shows which possibilities a combination off websockets and Apache Camel offers. The only downer is that both producer and consumer on server side. That means a producer can’t send a message to the consumer. For this you will need a client that performs the handshake. So it fits not 100% in the landscape of Apache Camel. But perhaps we’ll find a solution for this. If you’ve a suggestion drop a comment :)
[...] Eine detaillierte Anleitung hat Claus Straube zusammengefasst, womit die Demo in 10min auf jedem Rechner lauffähig sein sollte. Sourcecode ist unter GitHub verfügbar. Viel Spaß beim Testen! [...]
[...] my last article I showed, how to use websockets with Apache Camel. Today I will target a very special usecase: [...]
Question from a camel newbie: Is it possible to combine bidirectional CXF web services (producer & consumer) with a websocket transport?
First to say – I don’t have that much experience in CXF :) If I understand correctly the CXF WS acts as client to Apache Camel and is not part (as endpoint) of Camel? So if CXF acts as client I don’t think that it’s possible because client and server have to do a kind of handshake. This handshake logic must be implemented inside the client (e.g. Chrome or the newest Firefox have this functionality). I don’t think that CXF is websocket “ready”.