<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4626313203749706277</id><updated>2012-02-16T05:55:12.378-08:00</updated><category term='apache camel'/><title type='text'>On Camel and OSS</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://camelbot.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4626313203749706277/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://camelbot.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>hadrian</name><uri>http://www.blogger.com/profile/04807737204539914304</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>7</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4626313203749706277.post-1560697812317830167</id><published>2012-01-09T09:01:00.000-08:00</published><updated>2012-01-13T20:50:38.234-08:00</updated><title type='text'>How to protect the release GPG key</title><content type='html'>Recently I have been asked about how I handle the gpg key I use for Apache releases. For what is worth, the question popped up in the context of a few other community members taking on the release manager role. As those of you that follow Apache Camel already know the Camel PMC decided to actively support and issue patch releases for the two latest minor branches.&lt;br /&gt;&lt;br /&gt;But I digress. As I mentioned, I don't keep my private key on my laptop, but on an encrypted usb flash disk. The main reason is security, as the probability of someone getting access to my box greater than zero. In particular the key used for Apache releases is trusted by other ASF members and making sure it doesn't get compromised is one of the duties of the release manager. Of course one could revoke a key, but then verifying the integrity of a release becomes complicated at best.&lt;br /&gt;&lt;br /&gt;My setup works on Ubuntu 11.10 and the idea behind it was using something similar to &lt;a href="http://en.wikipedia.org/wiki/Two-factor_authentication"&gt;2-factor authentication&lt;/a&gt; (something I have and something I know). I use a relatively cheap 4G usb flash memory (a sturdier, metal one). My usb flash uses a FAT32 file system and is not encrypted, but on it I created a 256M file (ringo.img) as an encrypted ext3 disk partition. My usb flash is mounted as '&lt;span style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;/media/APACHE&lt;/span&gt;', not much to do about the uppercase, a perk of FAT32. The encryption uses 256-bit aes and sha512. Below are the commands I used to create my encrypted partition (inspired from &lt;a href="https://help.ubuntu.com/community/GPGKeyOnUSBDrive"&gt;this article&lt;/a&gt;).&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;sudo apt-get install cryptsetup&lt;br /&gt;cd /media/APACHE&lt;br /&gt;export usbdisk=$PWD&lt;br /&gt;dd if=/dev/zero of=$usbdisk/ringo.img bs=1M count=256&lt;br /&gt;&lt;br /&gt;sudo modprobe cryptoloop&lt;br /&gt;sudo modprobe dm-crypt&lt;br /&gt;sudo modprobe aes_generic&lt;br /&gt;export loopdev=$(sudo losetup -f)&lt;br /&gt;sudo losetup $loopdev $usbdisk/ringo.img&lt;br /&gt;sudo cryptsetup -c aes -s 256 -h sha512 -y create usbkey $loopdev&lt;br /&gt;&lt;br /&gt;sudo mkfs.ext3 /dev/mapper/usbkey&lt;br /&gt;sudo mkdir -p /media/encrypted&lt;br /&gt;sudo mount -t ext3 /dev/mapper/usbkey /media/encrypted&lt;/code&gt;&lt;/pre&gt;After that, the encrypted media should be working an mounted as '&lt;span style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;/media/encrypted&lt;/span&gt;'. The article explains how to write &lt;span style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;mount.sh&lt;/span&gt; and &lt;span style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;umount.sh&lt;/span&gt; scripts to automate the mounting and unmounting of the encrypted media. You need to make sure you don't forget to unmount your encrypted partition to avoid data loss, although the risk is in good part mitigated by the use of a journaled file system.&lt;br /&gt;&lt;br /&gt;Next is to setup gpg to use the keys from the encrypted file system. If you already use gpg, it's very simple. It stores the keys in a&amp;nbsp;&lt;span style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;.gnupg&lt;/span&gt;&amp;nbsp;directory in a user's home. The simplest way is to move the&amp;nbsp;&lt;span style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;.gnupg&lt;/span&gt;&amp;nbsp;directory on the encrypted media and create a softlink to it. As I want to be able to perform public key operations (encrypt/verify) even when my usb flash is not mounted, this is what I did:&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;mkdir ~/.gnupg-local&lt;br /&gt;cp ~/.gnupg/pubring.gpg ~/.gnupg-local&lt;br /&gt;cp ~/.gnupg/trustdb.gpg ~/.gnupg-local&lt;br /&gt;sudo mv ~/.gnupg /media/encrypted&lt;br /&gt;ln -sf /media/encrypted/.gnupg ~/.gnupg&lt;br /&gt;# unmount ringo&lt;br /&gt;sudo ln -sf ~/gnupg-local /media/encrypted/.gnupg&lt;/code&gt;&lt;/pre&gt;Note that the last command was executed after unmounting the encrypted partition. That way, if the encrypted partition is mounted the&amp;nbsp;&lt;span style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;.gnupg&lt;/span&gt;&amp;nbsp;softlink in my home will point to it, otherwise it will point to the softlink in the&amp;nbsp;&lt;span style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;/media/encrypted&lt;/span&gt;&amp;nbsp;which points back to&amp;nbsp;&lt;span style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;~/.gnupg-local&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;What I did is something slightly different, I wanted to avoid issuing a manual command every time I plug the usb flash in. The system that manages dynamic devices is udev, so I had to write a udev rule.&amp;nbsp;I made (renamed) copies of the mount and umount scripts in&amp;nbsp;&lt;span style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;/usr/local/sbin&lt;/span&gt;&amp;nbsp;and got rid of sudo in the scripts&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;-rwxr-xr-x  1 root root  449 2012-01-08 22:29 mount-ringo&lt;br /&gt;-rwxr-xr-x  1 root root  167 2012-01-08 22:29 umount-ringo&lt;/code&gt;&lt;/pre&gt;I added a udev rule:&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;hadrian@rem:~$ cat /etc/udev/rules.d/100-mount-ringo.rules &lt;br /&gt;ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="&lt;b&gt;1307&lt;/b&gt;", ATTRS{idProduct}=="&lt;b&gt;0165&lt;/b&gt;", RUN+="/usr/local/sbin/mount-ringo"&lt;/code&gt;&lt;/pre&gt;The &lt;span style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;idVendor&lt;/span&gt;&amp;nbsp;and&amp;nbsp;&lt;span style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;idProduct&lt;/span&gt;&amp;nbsp;values you can get from &lt;span style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;`lsusb`&lt;/span&gt;. They make sure the rule only fires when you mount the right usb flash memory. You can use other attributes to identify your flash if you prefer, like the label for instance.&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;hadrian@rem:~$ lsusb&lt;br /&gt;[...] &lt;br /&gt;Bus 003 Device 018: ID &lt;b&gt;1307&lt;/b&gt;:&lt;b&gt;0165&lt;/b&gt; Transcend Information, Inc. 2GB/4GB Flash Drive&lt;/code&gt;&lt;/pre&gt;You can test your rules using&amp;nbsp;&lt;span style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;`udevadm`&lt;/span&gt;. For that you need to know the mounted device which you can get if you know the label (&lt;span style="font-family: 'Courier New',Courier,monospace; font-size: x-small;"&gt;'sde'&lt;/span&gt;&amp;nbsp;in my case). If everything is ok, you should see a 'run: &amp;lt;your-script&amp;gt;' message near the end.&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;hadrian@rem:~$ ls -al /dev/disk/by-label/APACHE &lt;br /&gt;lrwxrwxrwx 1 root root 9 2012-01-09 11:13 /dev/disk/by-label/APACHE -&amp;gt; ../../&lt;b&gt;sde&lt;/b&gt;&lt;br /&gt;hadrian@rem:~$ sudo udevadm test /sys/block/&lt;b&gt;sde&lt;/b&gt;&lt;br /&gt;run_command: calling: test&lt;br /&gt;[...]&lt;br /&gt;ID_VENDOR_ID=1307&lt;br /&gt;ID_MODEL_ENC=USB2FlashStorage&lt;br /&gt;ID_MODEL_ID=0165&lt;br /&gt;ID_FS_LABEL=APACHE&lt;br /&gt;ID_FS_LABEL_ENC=APACHE&lt;br /&gt;ID_FS_UUID=6F8A-7C90&lt;br /&gt;ID_FS_UUID_ENC=6F8A-7C90&lt;br /&gt;ID_FS_VERSION=FAT32&lt;br /&gt;ID_FS_TYPE=vfat&lt;br /&gt;ID_FS_USAGE=filesystem&lt;br /&gt;[...]&lt;br /&gt;run: '/usr/local/sbin/mount-ringo'&lt;br /&gt;run: '/lib/udev/hdparm'&lt;br /&gt;run: 'socket:@/org/freedesktop/hal/udev_event'&lt;/code&gt;&lt;/pre&gt;Once you are happy with your test you can restart udev to use your new rule:&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;hadrian@rem ~$ sudo udevadm control --reload-rules&lt;/code&gt;&lt;/pre&gt;As a backup, you may want to put your private key on a non-encrypted usb flash that you don't use and is kept in a secure location. Now you should be all set, just pull your usb flash out and put it in your pocket and remember to always umount first. Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4626313203749706277-1560697812317830167?l=camelbot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://camelbot.blogspot.com/feeds/1560697812317830167/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://camelbot.blogspot.com/2012/01/how-to-protect-release-gpg-key.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4626313203749706277/posts/default/1560697812317830167'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4626313203749706277/posts/default/1560697812317830167'/><link rel='alternate' type='text/html' href='http://camelbot.blogspot.com/2012/01/how-to-protect-release-gpg-key.html' title='How to protect the release GPG key'/><author><name>hadrian</name><uri>http://www.blogger.com/profile/04807737204539914304</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4626313203749706277.post-5815206706251874983</id><published>2011-09-21T11:12:00.000-07:00</published><updated>2011-09-21T11:19:17.915-07:00</updated><title type='text'>The Case for Patch Releases</title><content type='html'>A new patch release of Apache Camel, version 2.8.1 was released last week. I didn't announce releases in a while. Why write about camel-2.8.1 then?&lt;br /&gt;&lt;br /&gt;The reason is that the Apache Camel community didn't produce patch releases in the past (we only did it for the 1.6.x version before discontinuing support for the 1.x versions). We actually started producing patch releases back in April for camel-2.7.x. At the time, I wasn't sure if and how this will continue because you need enough support within the community and some had the view that at Apache we should only focus on innovation.&lt;br /&gt;&lt;br /&gt;The untold truth about that though has to do with the business models of open source. ZDNet had an excellent &lt;a href="http://www.zdnet.com/blog/open-source/11-open-source-business-models/5371"&gt;article&lt;/a&gt; a while ago, which makes for interesting reading. The author left out another business model, let's name it &lt;a href="http://en.wikipedia.org/wiki/Fear,_uncertainty_and_doubt"&gt;FUD&lt;/a&gt; ware, that relies on bundling known, successful open source projects and claim that only your distribution is production ready and offers what the market needs. That works better if you have some influence over the community that produces the original open source project. It is not enough, that's for sure, but combined with other business models (such as 1. Support Ware or 4. Project Ware) it may make the needed difference.&lt;br /&gt;&lt;br /&gt;A few of us however, want the original ASF distribution to be stable, secure and production ready. After a bit of a struggle I am happy we managed to get the Apache Camel community used to the idea of producing patch releases more frequently. Between &lt;a href="http://www.dankulp.com/blog/"&gt;Dan Kulp&lt;/a&gt; and myself we issued since mid April three patch releases on camel-2.7.x, camel-2.8.1 last week and camel-2.8.2 is only a few weeks away.&lt;br /&gt;&lt;br /&gt;This way you, our users, won't have to wait at least a quarter to have your issues resolved. At the end of the day, you the users, are the Apache Camel community.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4626313203749706277-5815206706251874983?l=camelbot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://camelbot.blogspot.com/feeds/5815206706251874983/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://camelbot.blogspot.com/2011/09/case-for-patch-releases.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4626313203749706277/posts/default/5815206706251874983'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4626313203749706277/posts/default/5815206706251874983'/><link rel='alternate' type='text/html' href='http://camelbot.blogspot.com/2011/09/case-for-patch-releases.html' title='The Case for Patch Releases'/><author><name>hadrian</name><uri>http://www.blogger.com/profile/04807737204539914304</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4626313203749706277.post-2691056267834197488</id><published>2011-09-12T19:34:00.000-07:00</published><updated>2011-09-16T11:57:16.772-07:00</updated><title type='text'>Congrats Master Melegrito!</title><content type='html'>Personal things don't usually belong here, but this is a bit special. I am also still sore after this weekend.&lt;br /&gt;&lt;br /&gt;Once a year, me and Ama have the opportunity to go with our instructor, 4th Dan Tae Kwon Do Master &lt;a href="http://gokingtiger.com/"&gt;Josh Geeson&lt;/a&gt;, to train in self defense against stick and knife with Master &lt;a href="http://www.pmaa.info/"&gt;Julius Melegrito&lt;/a&gt;, event organized in Charlotte, NC by &lt;a href="http://www.kingtigercharlotte.com/introduction/meet-the-masters/73-master-evins"&gt;Master Evins&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;The seminar was a real treat as expected. Master Melegrito's speed and technique are amazing. After drills with two sticks, we got to one stick, repeating the same techniques. After the shoulders started burning we dropped the stick altogether and went mano-mano, repeating again, the same techniques only to realize how similar they are to Hapkido and Tae Kwon Do. Too bad this year we ran out of time and didn't get to practice defense against knife attacks. I am not complaining much though because last year my partner was Master &lt;a href="http://kingtigercharlotte.com/homesouth-charlotte"&gt;Robert Shin&lt;/a&gt; who's not very forgiving and the hardwood floor was, well, hard.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-xwfggN0y32g/TnOb1V4Au0I/AAAAAAAAAtI/c8VZD7QEgDU/s1600/melegrito-2011.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-xwfggN0y32g/TnOb1V4Au0I/AAAAAAAAAtI/c8VZD7QEgDU/s1600/melegrito-2011.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Yes, Ama, you are the best!&lt;br /&gt;&lt;br /&gt;What makes this year's event special is that Guro Melegrito is now a Black Belt Magazine 2011 Hall of Famer, the Weapons Instructor of the Year. Congrats Master Melegrito, many thanks for visiting and see you again next year!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4626313203749706277-2691056267834197488?l=camelbot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://camelbot.blogspot.com/feeds/2691056267834197488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://camelbot.blogspot.com/2011/09/congrats-master-melegrito.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4626313203749706277/posts/default/2691056267834197488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4626313203749706277/posts/default/2691056267834197488'/><link rel='alternate' type='text/html' href='http://camelbot.blogspot.com/2011/09/congrats-master-melegrito.html' title='Congrats Master Melegrito!'/><author><name>hadrian</name><uri>http://www.blogger.com/profile/04807737204539914304</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-xwfggN0y32g/TnOb1V4Au0I/AAAAAAAAAtI/c8VZD7QEgDU/s72-c/melegrito-2011.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4626313203749706277.post-127303024400660846</id><published>2011-09-07T19:00:00.000-07:00</published><updated>2011-09-07T19:00:36.857-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='apache camel'/><title type='text'>Annotation for the Claimcheck Pattern</title><content type='html'>The &lt;a href="http://eaipatterns.com/StoreInLibrary.html"&gt;claimcheck pattern&lt;/a&gt; is described in the &lt;a href="http://eaipatterns.com/"&gt;EIP book&lt;/a&gt; Camel is based on. The way it is described, the pattern uses a data store which means that it applies mostly to local processing. However, in most of the cases, at least in my experience, the processing is not local so one needs to retrieve the original message at a different location where access to the data store is not necessarily possible.&lt;br /&gt;&lt;br /&gt;As a bit of background, the commonly used analogy for the claimcheck pattern is the process used to check-in baggage while traveling and claim it at the destination. The rationale is that cabin space is a scarce resource (as is cpu, memory and bandwidth) and different parts of the in-flight entity have different SLA requirements: humans need oxygen, leg room, pressurized cabin space, food, entertainment, etc. whereas baggages can be stacked in the cargo hold. In some cases they may take different routes to destination as well.&lt;br /&gt;&lt;br /&gt;So how should this be implemented? Let's take a look at the elements that define the pattern. First we have a message that via some logic will be transformed into two messages (1).&amp;nbsp;&amp;nbsp;Let's call the two Messages the "initial message" and the "claim message".&amp;nbsp;That is the Content Filter part described in the pattern, not to be confused with the &lt;a href="http://camel.apache.org/message-filter.html"&gt;filter dsl&lt;/a&gt; in camel that is actually a &lt;a href="http://eaipatterns.com/Filter.html"&gt;Message Filter&lt;/a&gt;, very different thing.&lt;br /&gt;&lt;br /&gt;Our two messages will travel separately between departure and arrival, to borrow the terminology from the travel analogy&amp;nbsp;via two different&amp;nbsp;&lt;a href="http://eaipatterns.com/MessageChannel.html"&gt;Message Channels&lt;/a&gt;&amp;nbsp;(2), which in Camel we know as routes. The first message channel is the initial route we setup, let's call it the "main channel". The second channel is a one way one, let's call it the "baggage channel". Between departure and arrival, the &lt;i&gt;initial message&lt;/i&gt; will go on the bagage channel and the &lt;i&gt;claim message&lt;/i&gt; will go on the main channel.&lt;br /&gt;&lt;br /&gt;We also need to generate a &lt;a href="http://eaipatterns.com/CorrelationIdentifier.html"&gt;Correlation Identifier&lt;/a&gt; (3) to preserve the association (the equivalent of the bar coded tag on the baggage and the boarding pass). The fact that one could have multiple baggages is outside the scope of this pattern, it can be handled by a splitter/aggregator. The correlation id is both attached to the initial message and supplied somewhere in the claim message.&lt;br /&gt;&lt;br /&gt;The claim message will replace the initial message on the main channel and may undergo further processing. It may contain partial content from the initial message required for processing, it may need to be of a specific type, we cannot make many assumptions. Two things are clear though: it is produced from the initial message, so we need a Processor (4) for that, and it contains the correlation id, so we need an Expression (5) to extract it from there at destination. While we need to attach the correlation id to the initial message too, we have a bit more freedom on the baggage channel, so let's simplify things a bit and use a custom header/property instead of customizing too much and require another Expression.&lt;br /&gt;&lt;br /&gt;Putting together the five elements above, it starts to look like in the general case we need a separate, configurable one-way (in-only) route with some processing in the departure and arrival endpoints. I already looks like our implementation will actually require a different kind of Endpoint which also means a Component. It should support multiple queues at departure and arrival (i.e. both for check-in and claim). Since processing takes place on the main channel and at arrival during baggage claim the initial message is restored, it must be retrieved from the arrival claim queue, which means that the arrival queue must support random access. This is a key aspect, sometimes overlooked, that gives a lot of grief when implementing this pattern.&lt;br /&gt;&lt;br /&gt;As far as implementation goes, I started to play with a bit of code so you could see a solution in one of my next posts and probably in the Apache Camel trunk soon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4626313203749706277-127303024400660846?l=camelbot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://camelbot.blogspot.com/feeds/127303024400660846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://camelbot.blogspot.com/2011/09/annotation-for-claimcheck-pattern.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4626313203749706277/posts/default/127303024400660846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4626313203749706277/posts/default/127303024400660846'/><link rel='alternate' type='text/html' href='http://camelbot.blogspot.com/2011/09/annotation-for-claimcheck-pattern.html' title='Annotation for the Claimcheck Pattern'/><author><name>hadrian</name><uri>http://www.blogger.com/profile/04807737204539914304</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4626313203749706277.post-1766460183987211227</id><published>2010-10-31T20:34:00.000-07:00</published><updated>2010-10-31T20:34:22.250-07:00</updated><title type='text'>Apache Camel 2.5.0 Released</title><content type='html'>The 2.5.0 release of &lt;a href="http://camel.apache.org/"&gt;Apache Camel&lt;/a&gt; is finally out. It is the result of some two and a half months of improvements since the last release in July. You can check the &lt;a href="http://camel.apache.org/camel-250-release.html"&gt;release notes&lt;/a&gt; for more details and give it a &lt;a href="http://camel.apache.org/download.html"&gt;try&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The PMC is planning to focus now on releasing the 3.0 version of Camel in Q1 of next year. The 2.x version will continue to be actively improved for the foreseeable future (at least through 2011) and we plan to have another camel 2.x release this year.&lt;br /&gt;&lt;br /&gt;To help planning the new 3.0 release the Camel PMC conducted a survey during the month of October. Many thanks to all who participated in the survey and made their voice heard. The results of the survey will be made public this week during &lt;a href="http://na.apachecon.com/c/acna2010/"&gt;ApacheCon&lt;/a&gt;. If you want to see the goodies coming in the 3.0 version, keep an eye on the &lt;a href="http://camel.apache.org/camel-30-roadmap.html"&gt;roadmap&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4626313203749706277-1766460183987211227?l=camelbot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://camelbot.blogspot.com/feeds/1766460183987211227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://camelbot.blogspot.com/2010/10/apache-camel-250-released.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4626313203749706277/posts/default/1766460183987211227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4626313203749706277/posts/default/1766460183987211227'/><link rel='alternate' type='text/html' href='http://camelbot.blogspot.com/2010/10/apache-camel-250-released.html' title='Apache Camel 2.5.0 Released'/><author><name>hadrian</name><uri>http://www.blogger.com/profile/04807737204539914304</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4626313203749706277.post-2919954639727852238</id><published>2010-10-06T18:37:00.000-07:00</published><updated>2010-10-06T23:13:03.866-07:00</updated><title type='text'>Should you getIn or getOut?</title><content type='html'>From recent posts on the camel users@ mailing list there seems to be some confusion related to the use of getIn() and getOut() on a Camel Exchange. The question is relevant to developers who want to implement a processor and need to understand what should happen with the result of their processing. There is a &lt;a href="https://cwiki.apache.org/confluence/display/CAMEL/Using+getIn+or+getOut+methods+on+Exchange"&gt;wiki page&lt;/a&gt; that attempts to explain the usage of the two methods, but sadly that mostly fuels the confusion than clarifies anything. The page will be corrected soon, you may see a newer, corrected version, but at the time of my writing current is &lt;a href="https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=23338837"&gt;version 4&lt;/a&gt; (which was recently improved and a bit more accurate than &lt;a href="https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=23340000"&gt;version 2&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;So the idea (deeply rooted in some older discussion about what the Exchange api should be) is that you should use getIn(), because, uhm, "it's often easier just to adjust the IN message directly" and that has something to do with MEPs and a poor relative of camel called JBI. Before we get into more details, the reality is much simpler, using getIn() or getOut() has not much to do with MEPs and you should do what's right, which is process the in message (most likely), generate an out message (if needed) or update the in (sometimes).&lt;br /&gt;&lt;br /&gt;Camel is one of the integration space best frameworks (I'd think the best, but then you'll say I'm biased) and it is true that it was influenced by JBI. Some of its roots are in &lt;a href="http://servicemix.apache.org/"&gt;Apache Servicemix&lt;/a&gt; and three Camel PMC members have been at some point involved in drafting the jbi specs: &lt;a href="http://macstrac.blogspot.com/"&gt;James&lt;/a&gt; with jbi 1.0 and &lt;a href="http://gnodet.blogspot.com/"&gt;Guillaume&lt;/a&gt; and &lt;a href="http://bsnyderblog.blogspot.com/"&gt;Bruce&lt;/a&gt; with jbi 2.0. One of the main goals of Camel is to make integration simpler and more intuitive than jbi (and complement jbi in some cases).&lt;br /&gt;&lt;br /&gt;Now, just because the jbi 2.0 was inactive for a good while doesn't mean that the Camel Exchange API is broken as some may say. In particular, the jbi 1.0 spec says that "&lt;span style="font-style: italic;"&gt;The message exchange model is based on the web services description language 2.0 [WSDL 2.0] or 1.1 [WSDL 1.1]&lt;/span&gt;" (jbi-1.0-fr-spec, pg 5) and WSDL is pretty much alive and kicking. Then there is the discussion about the MEPs, which is 100% correct and 100% irrelevant. The reason is that the MEPs refers to the route not what happens within a particular Processor. You could use the exact same Processor on routes that are in-only or in-out.&lt;br /&gt;&lt;br /&gt;The concept though is much older than WSDL also. When implementing a function one would pass arguments and return a value. Think of a process() function that gets a Message as an argument and returns another Message.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;Message process(Message in) throws Exception;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;So the question then becomes should I return the same in Message or another one? Well, that's entirely up to you and what the process() function is supposed to do. The only thing that happens in Camel is that we wrap the two messages in an Exchange (plus the exception and some other metadata, because we needed an execution context) and that's what we pass to process(), so the function signature becomes:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt; void process(Exchange exchange);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;... which is pretty much the definition of the Processor interface. Or you can think of the exchange as being the stack frame prepared for the function execution in the first case (not much of a stretch).&lt;br /&gt;&lt;br /&gt;One important thing to note, that may clarify a bit the confusion is that getOut() will not really return the out message, but rather will lazily create an empty DefaultMessage for you (on the first call, and the existing out message on subsequent calls). Therefore there is no out message until you create it by calling getOut(), the assumption being that you called getOut() with the intention of returning the new distinct Message resulted from your processing. As a consequence the assertion getOut() ==null will always fail, because the getOut() call will create a message. To address that there is a hasOut() method in Exchange you could use to tell you if you created the out message (in case you don't know that already).&lt;br /&gt;&lt;br /&gt;As you probably know, what camel does is to pass an Exchange along the processor chain in a route and pass the out message of the previous processor as an in message for the next. If the previous processor did not produce an out (there are such processors, a logger for example, logs the in, but does not produce an out), then pass the previous in as an in message for the next processor. During its lifetime, an Exchange starts with an in, goes down the processor chain, outs are created and they replace the ins and the old ins are lost in history. And here's where the mep comes into the picture. If the route is in-out, at the end of processing chain, the last message in the exchange is passed back by the consumer to the caller, otherwise the last message is simply ignored (with an in-only mep, the caller is not waiting for an answer).&lt;br /&gt;&lt;br /&gt;A problem faced by users is that if they call getOut() and produce a new message, the headers from the in message get lost (well, the whole message gets lost). One thing to know is that if one needs to access some value at different points during processing, the Exchange has a property map. Objects in that map stay with the Exchange, unlike headers that are tied to messages (and probably have no semantics outside the message). As we saw, messages come and go during processing. Exchange properties don't. Now if you want headers to be preserved, you probably have a very specific processor, that can only exist in particular places in a route and make heavy assumptions about the type of in message they receive. If that's the case, yes, you probably only need to slightly modify the in message and since you did not create an out the modified in will be passed further down the route. If you need to update a header you set on a previous processor (such as a timestamp) but don't really rely on the in message per se, you might consider using exchange properties instead of headers. Consider also that even if you modify the in message to preserve the headers, other processors down the route may produce an out (and hence replace the current in) anyway so headers could still get lost down the route.&lt;br /&gt;&lt;br /&gt;That's pretty much it. Let's take a look at a few examples. A throttler processor will most likely not care about the in nor generate an out, it will only introduce a delay in processing (which may be adaptive and may depend on a header or property). A profiler processor will probably update timestamps in exchange properties, again ignoring the in, not producing an out and couldn't care less what the exchange pattern of the exchange is. A logger processor will log the in, won't produce an out, mep is again irrelevant. A crypto processor (partial message protection) will use credentials from the exchange properties to alter parts of the in message, sign/verify/encrypt/decrypt (may be either headers or parts of the body), will likely not produce an out. A proxy processor that allows you to integrate some legacy technology into a camel route, will use the input, format it according to the needs of the technology, use the proprietary api, get the result and put it as a new out on the exchange, possibly along with specific headers. A processor that fetches records from a database will most likely put the result set into a new out message as well. So again, should you use getIn() or getOut()? Things depend much on what your processor needs to do.&lt;br /&gt;&lt;br /&gt;Don't do what's easy, do what's right!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4626313203749706277-2919954639727852238?l=camelbot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://camelbot.blogspot.com/feeds/2919954639727852238/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://camelbot.blogspot.com/2010/10/should-you-getin-or-getout.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4626313203749706277/posts/default/2919954639727852238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4626313203749706277/posts/default/2919954639727852238'/><link rel='alternate' type='text/html' href='http://camelbot.blogspot.com/2010/10/should-you-getin-or-getout.html' title='Should you getIn or getOut?'/><author><name>hadrian</name><uri>http://www.blogger.com/profile/04807737204539914304</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4626313203749706277.post-3951727631382429429</id><published>2010-10-05T20:18:00.000-07:00</published><updated>2010-10-05T20:27:35.435-07:00</updated><title type='text'>Take the Apache Camel Survey!</title><content type='html'>A new &lt;a href="http://camel.apache.org/"&gt;Apache Camel&lt;/a&gt; release is just around the corner (version 2.5.0) and recently we announced taking the &lt;a href="http://camel.apache.org/2010/09/28/camel-riders-to-discontinue-support-for-1x-branch.html"&gt;1.x branch off life support&lt;/a&gt;. Therefore the race is on to deliver a new major version, Camel 3.0 early in Q1 2011 (see &lt;a href="http://camel.apache.org/camel-30-roadmap.html"&gt;roadmap&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;To that end the Camel PMC worked on a &lt;a href="http://s.apache.org/camel-survey"&gt;survey&lt;/a&gt; last week intended to get a better feel of how the community is using Apache Camel, what the major issues are (documentation, I know) and what improvements and new features you want to see in the next releases. The survey, sponsored by &lt;a href="http://www.sopera.com"&gt;Sopera&lt;/a&gt;, is anonymous and its results will be made public and used by the committers to create a remarkable experience for you.&lt;br /&gt;&lt;br /&gt;We care about you, our users, and, from the feedback we got so far, I am impressed by how much you care about us back. Your voice is important and it's one sure way to move the features you care most about higher on our priority lists and busy schedules. Needless to say, feel free to reach out to us on the &lt;a href="http://camel.apache.org/mailing-lists.html"&gt;mailing lists&lt;/a&gt; and &lt;a href="http://camel.apache.org/irc-room.html"&gt;IRC channel&lt;/a&gt; with questions and suggestions.&lt;br /&gt;&lt;br /&gt;So please take the survey (&lt;a href="http://s.apache.org/camel-survey"&gt;http://s.apache.org/camel-survey&lt;/a&gt;) if you didn't already and receive our gratitude for your continued support.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4626313203749706277-3951727631382429429?l=camelbot.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://camelbot.blogspot.com/feeds/3951727631382429429/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://camelbot.blogspot.com/2010/10/take-apache-camel-survey.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4626313203749706277/posts/default/3951727631382429429'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4626313203749706277/posts/default/3951727631382429429'/><link rel='alternate' type='text/html' href='http://camelbot.blogspot.com/2010/10/take-apache-camel-survey.html' title='Take the Apache Camel Survey!'/><author><name>hadrian</name><uri>http://www.blogger.com/profile/04807737204539914304</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
