Just few general comments on the topic here: 1) My impression is that we are trying to solve problem that doesn't exist. No one would expect that getting "foo" header should retrieve what was put under "FOO" key. If we want to have guarantee that it works properly people should use constants for it. It is the way that Java world solves those problems 2) If we create CaseInsenstiveMap class we will fail to obey Map contract. Let's take a look at Map.containsKey() method's contract in javadoc. And my impression is that we want to treat headers as a Map, don't we?
In protocols that has case-insensitive headers (like http) I believe component should take care of it by (for example) setting headers using lowercase keys only (for example) and it should be clearly stated in component's documentation, as in Camel components are responsible for handling protocol-specific features. By having headers (that are Map basically) case-insensitive I believe we change Camel internals so it conforms to specific features of specific protocols. We did it already by having faults as separate messages, by having attachments in the Camel message - I believe those things were wrong and we already fixed some of them. Roman 2009/8/10 James Strachan <james.strac...@gmail.com>: > FWIW I'm liking the fact that lookups become case insensitive; as its > what folks expect in HTTP/Mail type scenarios. Using a custom Map also > makes it possible for a component/endpoint to disable this feature if > it wishes (or use a different Map implementation if it can think of a > good reason to do so). > > 2009/8/10 Claus Ibsen <claus.ib...@gmail.com>: >> 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<hzbar...@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.ib...@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 >> > > > > -- > James > ------- > http://macstrac.blogspot.com/ > > Open Source Integration > http://fusesource.com/ >