Bug 734059
Summary: | If Message-driven bean used with topics, message delivered 15 times | ||||||||
---|---|---|---|---|---|---|---|---|---|
Product: | Red Hat Enterprise MRG | Reporter: | Jiri Sedlacek <jsedlace> | ||||||
Component: | qpid-jca | Assignee: | Jiri Sedlacek <jsedlace> | ||||||
Status: | CLOSED CURRENTRELEASE | QA Contact: | MRG Quality Engineering <mrgqe-bugs> | ||||||
Severity: | high | Docs Contact: | |||||||
Priority: | urgent | ||||||||
Version: | 2.0 | CC: | astitcher, jpechane, jross, oskutka, rattapat+nobody, tross, wprice | ||||||
Target Milestone: | --- | ||||||||
Target Release: | --- | ||||||||
Hardware: | Unspecified | ||||||||
OS: | Unspecified | ||||||||
Whiteboard: | |||||||||
Fixed In Version: | Doc Type: | Bug Fix | |||||||
Doc Text: | Story Points: | --- | |||||||
Clone Of: | Environment: | ||||||||
Last Closed: | 2012-12-10 21:35:39 UTC | Type: | --- | ||||||
Regression: | --- | Mount Type: | --- | ||||||
Documentation: | --- | CRM: | |||||||
Verified Versions: | Category: | --- | |||||||
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||||
Cloudforms Team: | --- | Target Upstream Version: | |||||||
Embargoed: | |||||||||
Attachments: |
|
Description
Jiri Sedlacek
2011-08-29 10:57:57 UTC
Created attachment 520964 [details]
reproducer maven project
I need more information, please provide the configuration you are using. Sorry, didn't see the attachment, I will review. First of all please do not use the old BURL syntax. All of our documentation is now using the new addressing syntax. Since MRG 1.3 the default syntax has been address strings - not BURL! For completeness, the following BURL is not a topic! destinationAddress=direct://amq.direct//topic.Hello?routingkey='topic.Hello' If you wanted to use a topic is should have been, destinationAddress=topic://amq.topic//topic.Hello?routingkey='topic.Hello' Again I stress that we need to keep testing JMS and JCA with destination configured using the address syntax since that is what we have put in our documentation. As far as I was able to debug the code, the jca adapter needs to use only binding URL, no address syntax. Please see https://bugzilla.redhat.com/show_bug.cgi?id=700494 However, even with this bug, you should still use ADDR syntax. As per Rajith's comments, ADDR is the default mechanism and the underlying JMS client will correctly handle ADDR destination strings. Again, this appears to be misconfigured either way since you want a topic, but as Rajith points out your original string this is not configured correctly. Weston, the functionality to use ADDR syntax IS NOT present in JCA adapter (and won't be even in 2.0.4 version, as mention un Bug 700494), so we definitely need a way how to properly configure jms queue and topic with BURL syntax. Please provide functional and verified examples, because our testning is blocked by that. This issue (as was reported) is not related to topic or direct exchange from the qpid point of view, the same situation is when I use amq.topic in BURL. The only difference between direct and topic exchange is in delivering messages to queues regarding to routing_key and binding_key. This is qpid point of view. The topic in JMS api has completely different meaning. The problem is, that if MDB is deployed and bound to JMS topic, the 15 instances of the class are created and each instance obviously has it's own consumer and own connection (and it's own queue on the qpid side), and from the behavior of JMS topic, the message is delivered to every consumer currently connected. But expected behavior is just one message delivered to MDB, even if 15 instances of the same MDB are created. 'But expected behavior is just one message delivered to MDB, even if 15 instances of the same MDB are created.' For queues this is correct, for topics it is not. The pub/sub messaging domain is designed to allow messages to be delivered to multiple subscribers, that is in fact what pub/sub means. For MDB's, every MDB instance that has 'subscribed' to a topic will receive the message. If you want only once delivery, you would use a Queue (point-to-point domain) not a Topic. You can limit the number of sessions for the adapter by setting the property: @ActivationConfigProperty(propertyName = "maxSession", propertyValue = "1") This will give you the behavior that you want, but again, it is not applicable for pub/sub as in the above example, what you really want to use is a Queue, not a Topic since you only want one consumer/listener to receive the message. I am attaching jca-examples.jar which is a rework of the JCA examples providing much more realistic examples for Queue/Topics, syntax etc. This should give better examples that what was previously provided. There is a BZ for this 735322, but I thought I would get the work out early so you can start taking a look. Alternatively you can check it out from GitHub as well: git://github.com/astitcher/qpid-jca.git branch is wp-BZ-735322 Created attachment 521455 [details]
Updated examples to aid in testing
Note, a word about Queues/Topics and JCA in general: As previously mentioned, Topics are used for the pub/sub style of messaging. As such, ANY subscriber to a particular topic receives the message as opposed to queues. This would be the case independent of JEE and JCA. This is basic JMS. If you have two subscribers to a particular topic BOTH those subscribers will receive the message. In EE, the EJB container is responsible for managing message listeners (in our case, JMS MDB's). The container creates (n) number of MDB instances for each deployment, manages their lifecycle etc. In the case of an MDB listening/subscribing to a Topic, ALL instances of the MDB will receive a message. This is how Topics, and pub/sub in general works. Again, this is standard JMS. This is not the case for queues, where one, and only one, consumer will receive the message (this assumes of course you have things configured correctly). The MRG-JCA adapter is responsible for 'adapting' the MRG Broker into a JEE environment. When it comes to the delivery of messages, the ONLY API the JCA adapter uses is is JMS. There is no inherent JCA 'magic' under the hood. The process is pretty simple conceptually: 1) When an MDB is deployed, the EJB container passes the ActivationSpec to the JCA adapter. This is usually referred to as 'activating' the endpoint (endpoint is the MDB basically). 2) The adapter uses the properties of the activation spec to configure the necessary objects to support delivery to the MDB. Note, this is roughly the same process as you would execute when setting up a MessageListener outside of a JEE environment. a) Setup ConnectionFactory (in JEE, this usually means just pulling it from JNDI) b) Setup Destination (in JEE, this usually means just pulling it from JNDI) c) Create the Connection d) Create the Session e) Register an exception listener f) Create a consumer or describer as per the type of Destination (i.e. queue or topic respectively) g) Set's the MessageListener on the consumer or subscriber i) Set's up XA support if necessary (or local transaction) j) Start's the connection allowing incoming messages. That's it. So, again, with JCA itself is a complex subject, in the context of JMS it's really quite understandable. If your ever in doubt about what JCA/JMS is, simply think about what would happen outside of the context of JCA. Returning to our original point, if you have multiple subscribers to a Topic, then each on of those subscribers is going to receive a message for that Topic. You have multiple consumers on Queue, only one will get the message. If the above explanation(s) are sufficient, please close this issue. Weston, I'm aware of how pub/sub model with jms topics works and I understand the whole process of deploying MDB (what is done and how). The problem is, that MRG JCA adapter behaves differently from JBossMessaging or HornetQ and this can be confusing for users/customers. I understand, that each instance of MDB (default is 15) is independently connected to qpid server and thus each one receives the message. I don't know the inner implementation of JBossMessaging or HornetQ, but MDB used with both of them, even if 15 instances of the same MDB is created (which is default number), receives one message from the jms topic just once (it's discussed also here: http://community.jboss.org/message/541041). I cannot decide which is correct, EJB specification lacks this case. But It probably will be better to have same behavior as all other messaging providers from our company, or document this feature clearly and carefully for customers to know what they should expect. Ah, ok, you mean DURABLE topics, you did not mention this. Unfortunately, for this configuration each subscriber requires a unique subscription id in the case of a durable topic. This is mandated by the JMS specification. Unfortunately, we do not implement this feature today in the JCA adapter where we would generate a unique subscription id. As such, this doesn't work out of the box. So, this most likely is a feature request since you can achieve the exact same semantics through the use of queues. It is somewhat questionable to have multiple subscribers for a durable topic to balance workload as again, you get this with queues anyway. However, it is indeed something we are lacking with durable topics. In thinking about this, the other way to achieve what you want is by what I mentioned before: @ActivationConfigProperty(propertyName = "maxSession", propertyValue = "1") When you set this, only one Session will be created as a result, your client_id and subscription name will be unique. Note, this has nothing to do with the MDB instance pool, there are still multiple MDB instances since there isn't a 1-1 correspondence between Sessions and MDB instances. This will give you the behavior that you are looking for however, a few things to keep in mind again: 1) This is really non-standard behavior and just because HornetQ, or another JMS provider manages this, it's probably not enough to claim that this is a defect. 2) The same effect can be achieved using queues which is really the 'correct' way to achieve this messaging style. 3) Limiting the max sessions will also give you want you want as well, so I believe we can say we do 'support' this feature via configuration. If this is sufficient, please close this issue. Weston, also oracle writes and does what I said: http://download.oracle.com/docs/cd/E12840_01/wls/docs103/ejb/message_beans.html ad 1/ this should be standard for us, if majority of our messaging providers does it. If we certify this for customers to be able to smoothly start using MRG, it should behave in the same way. You maybe don't agree with me, but this have to be resolved by PM. ad 2/ the same effect cannot be achieved by queues, if you need two different MDBs (maybe on different hosts) to receive one message, you need them to be connected to topic. ad 3/ limiting the max sessions can affect performance, can't it? ad 1/ Whether I disagree or not is really irrelevant. As you point out, this is a PM decision. We just don't do it today. In regards to other application servers, I am not sure if this is a valid argument as there are plenty of differences in regards to functionality between app servers as well as messaging providers. Again, this is just my opinion. ad 2/ I'm not quite sure I follow. Two MDB's (both on different hosts), both configured to listen to a queue, one MDB will receive the message the other will not. Where these MDB's are located is irrelevant. The behavior that you are asking for, as far as I can tell, is to load balance across topic listeners pointing to one durable subscription to achieve the effect that only ONE instance of the MDB receives the message. Again, this is point-to-point behavior exactly and is the complete opposite to the way Topics work So, my real question is what exactly is the benefit of this topology configuration beyond the reason of 'If they do it, we should do it?' Again, if I am missing something, then I apologize. ad 3 Yes, there is always a performance hit. It was simply mentioned as a 'sort of' workaround, that was all. Also, in reviewing the Oracle doc, I am looking for the place in the documentation that says: 'You can configure Topic listeners so as to only have only one subscriber receive the message versus every instance in the pool'...or something equivalent. From the doc you posted: ' In contrast to a point-to-point application, in a publish/subscribe model, a message is processed by one instance of each of the subscribing MDBs. Message “M1” is processed by an instance of MDB_A and an instance of MDB_B. Similarly, “M2” is processed by an instance of each of the subscribing MDBs.' So, again, could you point to me in the doc where it says you can configure topic subscribers so that only one instance gets a message? This might help clarify when this would be useful. I think so far this discussion boils down to "Should this work be targeted at 2.0.4 as well as 2.2? or will doing it just for the later release suffice?" Doing this for 2.0.4 would likely be somewhat different from doing it for 2.0.4 as the code bases have already diverged somewhat, it would likely double the implementation effort. You selected the exact sentence from the oracle guide, which describes it. In pub/sub model, for each connected MDB just one instance receives message from topic, not all instances. This could be useful, e.g. if you want to start two asynchronous servises by just one message, you have to send it to the topic and both two services will receive it a can do whatever with it. With queue, it's not possible, just one of these services will receive the message and you don't know which. As a result of the above discussion, while we don't do this today, I agree with the reporter that this will be a valid feature in the future. As such, I am changing the devel_ack flag to devel_ack- and changing the target milestone to 2.0.10. After doing some more investigation I have a status update in regards to this issue. In talking with QE, HornetQ team etc, I believe we currently do not implement this correctly.
For JEE MDB's subscribing to a non-durable, JMS topic, the behavior SHOULD be that the message gets delivered only once. This is not happening because on deployment, we create n consumers per n number of sessions (by default, we create 15). Each one of these consumers/subscribers creates a uniquely identified temp queue which in turn causes a single message to be delivered 15 times (as the original BZ stated).
There are three workarounds/solutions:
1) Limit the number of sessions to 1 for Topics.
2) Use queues instead of Topics
3) A new solution would be to create the Topic with the following syntax, or something similar:
destinationAddress=amq.topic/hello.Topic;{link:{name:hello-topic,x-subscribe:{exclusive:false}}}
using the above syntax we set it up the link to where the same name is shared across multiple sessions and the topic is not exclusive. This is in effect the same default behavior as queues, but will work in the case of MDB's and Topics to get the equivalent behavior of HornetQ/JBM etc. HornetQ does something similar in their JCA/JMS client, here we are simply specifying this behavior to the server.
Approach #3 would be preferred...HOWEVER, currently the JMS client does not allow for non-exclusive Topics
>>
if (dest.getDestSyntax() == AMQDestination.DestSyntax.ADDR)
{
if (dest.getAddressType() == AMQDestination.TOPIC_TYPE)
{
return true;
}
else
{
return dest.getLink().getSubscription().isExclusive();
}
}
<<
so this option is not available at this time. I am going to file a JIRA upstream and a new BZ to allow for this option and link it as a dependency for this issue.
Good work on QE's part again in identifying a discrepancy in the JMS providers behavior. Similarly, our documentation should be updated to identify the differences in behavior and the proposed workarounds. Once #3 gets implemented, I believe this should be the default behavior for our MDB/Topic configurations in the examples.
In talking with Rajith, the following string would work as well in getting around the exclusive 'bug' destinationAddress=hello-topic; {create: always, link : {x-bindings:[{exchange: 'amq.topic', key : 'hello.Topic'}]}} You can use this syntax to test and close this bug. We are going to rethink the process we use for creating/managing topics in a later release. I tested this string destinationAddress=hello-topic; {create: always, link : {x-bindings:[{exchange: 'amq.topic', key : 'hello.Topic'}]}} and it solves the problem with 15 messages to one MDB (tested version 3.0) on topic. Jiri, could you please have a look and mark verified ? I'm moving this to modified as the latest JMS rpms (or any recent rpms with addressing support) can support the above string. Rajith |