|
|
||
David Walend's BlogBrilliant Approach to Optional Data Design? Wicked Hack? Source of Horrible Suffering?Posted by dwalend on June 05, 2006 at 07:11 PM | Comments (1)I've finally added message selector support for Topics in SomnifugiJMS, a single-process implementation of a Java Messaging Service. It's SomnifugiJMS's 14th alpha release. (Message selectors for Queues will be more difficult, but is the last piece keeping SomnifugiJMS in alpha releases. I think I can get it to work with j.u.c.Conditions and some extra work, but haven't had the time to design it yet.) At JavaOne, I met up with Linda Schneider, one of the key people working on https://mq.dev.java.net/, at JavaOne. She sent me a pointer to the message selector implementation in the JMS reference implementation. The JMS RI just switched to CDDL, which is a file-based license, so I picked up their code, edited it to play nice with my own, and now have message selectors for Topics. They even have a good set of tests in a main method; the JMS RI predates JUnit by a year or so.The only snag I hit was that I use member fields in SomniMessage to hold information that every message should hold, but the JMS RI Selector API expects a Map.
My first thought was to recode the JMS RI Selector to use javax.jms.Message-specific getters. That sounded tedious; I'm not familiar with the code, and am not overly interested in writing or modifying an SQL92 parser. Linda emailed, "[Selector.java is] huge because there is a lot of different items to parse," which seems to say it all. My second thought was to recode SomniMessage to use a Map to store this sort of information. In SomnifugiJMS these fields always have some value, so a Map just seems wrong. SomnifugiJMS is supposed to be faster and simpler than database JMS implementations, especially for small-scale work (which rarely needs message selectors). I didn't want to loose that simplicity to get the message selectors working. I pondered a bit and came up with a third option: use reflection to implement a Map that calls getters when given a field name as a key:
I could implement a general purpose put() method by slipping another Map inside this one, and delegating put()s and get()s to that map for keys that hasGetters does not have. I can't implement the whole Map interface this way because there's no way to remove arbitrary keys. What would removing a field even mean? I think that's an interesting piece of code, especially given the talk of invokeDynamic's evil partner, "changing the members of an object," at a JavaOne talk. It's an interesting choice for sometimes-optional fields when designing data structures. However, "Interesting" might mean that it'll be a source of horrible suffering.
First, code that works this way will have to have Second, the keys are Strings, so there's no great way to predict what might be a key. For message selectors, I know from the JMS specification that the keys will be a small, defined set of Strings that happen to match method names. Perhaps an Enum of possible keys would better define the universe of possible optional members, but that shifts back toward the unsatisfying "this member hasn't been set yet" pattern for accessors. I can live with these problems in my own code, but I want to know these land mines are out there, especially after a decade of trying to avoid using nulls as magic error codes. In my ears: Beethoven's Missa Solimnis. Wow. Bookmark blog post: CommentsComments are listed in date ascending order (oldest first) | Post Comment
| ||
|
|