
|
If you were logged in you would be able to see more operations.
|
|
|
RHQ Project
Created: 01/Apr/08 12:25 PM
Updated: 04/Feb/09 09:16 AM
|
|
| Component/s: |
FX - Alerts
|
| Affects Version/s: |
0.1
|
| Fix Version/s: |
None
|
|
| Date of First Response: |
15/Apr/08 06:37 AM
|
|
The Alert Condition Consumer Bean does not seem to be honoring its @EJB reference dependencies. If there are messages in the queue at startup, the consumer will grab them before startup finishes and will start getting tons of errors until the other referenced beans start.
|
|
Description
|
The Alert Condition Consumer Bean does not seem to be honoring its @EJB reference dependencies. If there are messages in the queue at startup, the consumer will grab them before startup finishes and will start getting tons of errors until the other referenced beans start. |
Show » |
|
The only ordering guarantee that the deployer gives us is that services with dependencies -- and @EJB creates an implicit dependency -- will have their deps started first. Our problem is that our SLSB layer has many cycles in the dep graph, and we break those cyclic dependencies via the use of (at the date of this writing) 23 instances of @IgnoreDependency.
Unfortunately, if there are messages in the queue at startup, then the MDB is apparently started early in the deployment of the EJB module. Here is the sequence of events that are failing us.
MDB -> A -> B -> @Ignore...C -> D -> B
Notice the cycle between B, C, and D. B needs C to be started, C needs D to be started, and D needs B to be started. When those services were developed, no attention was paid to which service got the @IgnoreDependency annotation affixed to it, but because the MDB now wants to process messages, *it* will initiate other service starts by following its dependency graph.
Clearly, when the deployer gets to service B, it notices that it can ignore the dependency on service C, and it does. However, when the deployer is done doing its job and hands control back over to the MDB, some of the needed downstream services aren't in the started state.
It picks the next message from the queue, and the MDB interacts with A, and A interacts with B, and when B tries to interact with C -- boom. The EJB container complains that the B.referenceToC has not been initialized / is not a valid reference / etc.
One solution to this would be to simply move the cyclic dependency downstream from the MDB caller. If the dep graph had looked like:
MDB -> A -> B -> C -> D -> @Ignore...B
Then things would have "just worked." In this scenario, even though B isn't explicitly started as a dependency of service D, it *will* be started before control is passed back to the MDB. D finishes and is put in the started state, which allows C to start, which allows B to start (ah, see, we didn't need to start B further downstream, because it was already on the path), which allows A to start, and finally control is passed back to the MDB. This time, when the MDB picks a message off the queue, all necessary downstream services are started correctly.
However, there's one big issue with this solution. If over the evolution of your service layer, you add more and more MDBs, then you need to make sure that *all* of them abide by this rule. Unfortunately, there can (and will) be instances where different MDBs share some of the same downstream dependencies, and therefore will have mutually exclusive solutions using this rule. In other words, if you fix one dependency chain, you break another, and vice versa.