camel-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Claus Ibsen <claus.ib...@gmail.com>
Subject Re: [DISCUSS] - Camel 2.0 - Case insensitive headers on Camel Message
Date Mon, 10 Aug 2009 09:16:13 GMT
Hi

Had a chat James as well.

Went for the solution without a KeyValuePair object as it causes pain
with dynamic languages and template engines. And the camel-jms
component had some obscure errors with it also.

Its very easy to revert to old behavior as its just to change to use a
java.util.HashMap in DefaultMessage.


On Sat, Aug 8, 2009 at 9:53 PM, Hadrian Zbarcea<hzbarcea@gmail.com> wrote:
> 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
>
>



-- 
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