|Schema-oriented message destination
Ricky Ho (email@example.com)
When a message producer send a message to a destination (queue or topic), he wants to make sure that he is sending messages to a destination where the consumers can understand. Similarly, when a message consumer receive a message from a destination, he wants to make sure that he can understand all messages he take from the destination.
In JMS, the producer and consumer are tightly coupled with the message structure. However, there is no relationship between the destination and the message structure. Therefore, the consumer application and producer application needs to agree upfront (at design time) what message structure will be produced or consumed.
There is NO standard way for a new producer app or consumer app to learn what message structure they should be used for a destination. They will try to look for existing design documents to find if they mention anything about the message structure. Nevertheless, the only reliable way is to look at source code from existing producer and consumer app. This process is error-prone.
If the consumer consumes a message from a queue with an unexpected structure. At best, it detects the message is not understandable and drops it, in this case the message is lost. At worst, the message with wrong structure will crash the consumer app. Well-written consumer applications will take the burden to code the message structure validation logic, resulting in undesirable complexity. Ideally, the message structure should have been verified before passing to the consumer application.
Whenever a change is needed for a message structure (usually initiated from one of the message producer), nightmare start. First, we need to trace all the destination where the new message (with the changed message structure) will go to. Second, for each of the destination, we need to trace all the consumer applications and make sure that they are changed apropriately to deal with the new message structure. This tracing can be very difficult when the consumer application dynamically subscribing and receiving from destinations. If we miss the upgrade for one consuming app, we are introducing problem 2.
A destination should only accept one type of message with a particular message structure. The metadata associated with each destination should include the definition of this ONE message structure that it accepts.
Whenever a message is sent to a destination, the JMS container should verifies the message with the specified structure.
Whenever a change is made to a message structure, a new version of destination (by destination naming convention)is created, at the same time all existing consumer applications will received a callback method "onSchemaChange()". Now this new destination will only accept message with the new (changed) message structure. Old producer app without aware of the message structure change can keep sending message with old structure to the old destination which will be consumed by old consumer apps. Because, existing consumer apps will never receive the new message type until they explicitly change to the new destination, they won't break. This mechanism requires the producer and consumer applications to explicitly move to a new destination and accomodate the message structure changes at the same time.
By enforcing the association between a destination with a message type. We can standardize the mechanism how the producer app and consumer app discover the correct message schema.
By introducing metadata of the destination, a producer app and consumer app can examine that at run time, and hence reducing design-time assumptions.
The destination versioning helps to prevent incompatibilities problems when schema changes.