camel-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Hadrian Zbarcea <hzbar...@gmail.com>
Subject Re: [DISCUSS] - Camel 2.0 - Case insensitive headers on Camel Message
Date Sat, 08 Aug 2009 19:53:04 GMT
Hi Claus,

I added a comment on the Jira as well.

Why not use a Map<lowercase-header, Pair<header, Object>> ?  I believe  
this to be a simple solution.  Lookups should always be on the  
lowercase version of the header, on the wire the original version  
should go.

What do you think?
Hadrian

On Aug 8, 2009, at 9:42 AM, Claus Ibsen wrote:

> Hi
>
> I have just attached a much better implementation of the map, this
> time all code is in a single class and it does not use holder objects
> such as a KeyValuePair when storing the value.
>
> It also works out of the box with scripting engines that can access
> and manipulate the headers such as Freemarker and Velocity.
>
> The changes needed in DefaultMessage is basically to use this map
> instead of a regular HashMap.
> And when its copied to another map the original keys is automatic  
> retained.
>
>
>
> On Sat, Aug 8, 2009 at 12:42 PM, Claus Ibsen<claus.ibsen@gmail.com>  
> wrote:
>> Hi
>>
>> For background see ticket CAMEL-1886
>> https://issues.apache.org/activemq/browse/CAMEL-1886
>>
>> The issue is that headers is stored using keys that are case
>> sensitive, and that leads to a few problems and differences in Camel:
>>
>> - lookup is cumbersome as you must match case 100%
>> - errors in camel components that is unable to realize a header
>> already exists however with a different (case)
>> - some protocols are agnostic to header cases, such as HTTP (and all
>> its different transports using HTTP), Mail, and whatnot?
>> - camel-mail stores notoriously headers in lower keys only
>> - etc.
>>
>> And most importantly
>> - no one wants to send different values using a key that have
>> different case, such as:
>>  Foo=cheese
>>  FOO=cake
>>  foo=beer
>>
>> So James and I had a chat about it and to see if would could do
>> something about it.
>>
>> The real reason that I picked up this issue is the tuning experiment
>> with Camel 2.x
>> http://camel.apache.org/camel-2x-speed-optimizations.html
>>
>> Where we want to take a few short cuts and offer header lookup on the
>> source directly to avoid the "tiny" overhead of extracting headers
>> from the source
>> and populate the camel message. This is useful if you do message
>> routing that only uses headers. The camel-jms component did already
>> offer this but
>> it also had some inconsistency in this relation.
>>
>>
>> I have attempted a resolution in the tuning branch but discovered an
>> issue, that it does take some more grunt work to keep the lower case
>> index in sync etc.
>> So I wanted to try a different approach
>>
>> CaseInsenstiveMap
>> ===============
>>
>> I have implemented a small case insenstive map so we can store  
>> headers
>> in 1 map instead of keeping 2 maps in sync.
>> I am still amazed why such a Map does not exists directly in the  
>> JDK itself.
>>
>> What does this offer then
>> - lookup is easy as you can lookup using any case
>>  and in the future we could also offer lookup for special keys people
>> spell differently such as: ContentType, content-type, content-type,
>> content_type and whatnot.
>> - put will also ensure that it replaces existing values
>> - and most importantly that it offers this as well when end users  
>> work
>> directly on the map using:
>>     exchange.getIn().getHeaders().put("foo", "beer")
>>  That will be able to replace existing keys if they are stored using:
>> Foo, FOO or what not
>>  This is not possible today and or with a 2nd map that tracks lower
>> case indexes
>>
>> So how to retain the original keys.
>>
>> Well I implemented that as well, so when you e.g. copy the map to
>> another or extract from it using keySet it exposes a Set that uses  
>> the
>> original key cases.
>> So if you have stored using
>>   exchange.getIn().setHeader("Foo", "cheese")
>>
>> Then the key in the ketSet is the original key = Foo.
>> But you can do lookup using: foo, FOO, FoO, FOo, and whatnot :)
>>
>> Using this implementation I actually find a few bugs in existing unit
>> tests and camel components that double add headers using different
>> cases.
>> For example camel-cxf in the new RS support.
>>
>>
>> I will later attach the code to the CAMEL-1886 ticket for people of
>> the community to take a look and review.
>>
>>
>> Here is a snippet from one of the test methods to give an idea
>>
>>    public void testLookupCaseAgnosticAddHeaderRemoveHeader() {
>>        Map<String, Object> map = new CaseInsensitiveMap();
>>        assertNull(map.get("foo"));
>>
>>        map.put("foo", "cheese");
>>
>>        assertEquals("cheese", map.get("foo"));
>>        assertEquals("cheese", map.get("Foo"));
>>        assertEquals("cheese", map.get("FOO"));
>>        assertNull(map.get("unknown"));
>>
>>        map.put("bar", "beer");
>>
>>        assertEquals("beer", map.get("bar"));
>>        assertEquals("beer", map.get("Bar"));
>>        assertEquals("beer", map.get("BAR"));
>>        assertNull(map.get("unknown"));
>>
>>        map.remove("bar");
>>        assertNull(map.get("bar"));
>>        assertNull(map.get("unknown"));
>>    }
>>
>>
>> And when using the Message API
>>
>>    public void testRemoveWithDifferentCase() {
>>        Message msg = new DefaultMessage();
>>        assertNull(msg.getHeader("foo"));
>>
>>        msg.setHeader("foo", "cheese");
>>        msg.setHeader("Foo", "bar");
>>
>>        assertEquals("bar", msg.getHeader("FOO"));
>>        assertEquals("bar", msg.getHeader("foo"));
>>        assertEquals("bar", msg.getHeader("Foo"));
>>
>>        msg.removeHeader("FOO");
>>
>>        assertEquals(null, msg.getHeader("foo"));
>>        assertEquals(null, msg.getHeader("Foo"));
>>        assertEquals(null, msg.getHeader("FOO"));
>>
>>        assertTrue(msg.getHeaders().isEmpty());
>>    }
>>
>>
>>
>>
>>
>> --
>> Claus Ibsen
>> Apache Camel Committer
>>
>> Open Source Integration: http://fusesource.com
>> Blog: http://davsclaus.blogspot.com/
>> Twitter: http://twitter.com/davsclaus
>>
>
>
>
> -- 
> Claus Ibsen
> Apache Camel Committer
>
> Open Source Integration: http://fusesource.com
> Blog: http://davsclaus.blogspot.com/
> Twitter: http://twitter.com/davsclaus


Mime
View raw message