While migrating a JBoss 5 application to JBoss AS 7 (7.1.1.FINAL) I have a problem with a new JMS message driven EJB. Within message processing, some master data fields have to be checked. To enhance performance, this master data shall be preloaded into a cache structure using a @Singleton @Startup
EJB, which needs about 30 seconds to load the data.
My problem is that the queue message processing starts even if the cache has not been fully initialized, causing message validation errors.
I tried to define a dependency between the MDB and the startup EJB, but as far as I understood the @DependsOn
annotation works only with @Singleton
EJBs. So it's clear that my solution does not work ;-)
Startup bean code:
@Singleton
@Startup
public class StartupBean {
@PostConstruct
void atStartup() {
// TODO load master data cache (takes about 30 seconds)
}
@PreDestroy()
void atShutdown() {
// TODO free master data cache
}
}
Note: I stripped the real code from the example to make it easier to read :-)
Message driven bean code:
@MessageDriven(name="SampleMessagingBean", activationConfig = {
@ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
@ActivationConfigProperty(propertyName="destination", propertyValue="jms/SampleQueue"),
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge")
})
@DependsOn("StartupBean")
public class SampleMessagingBean implements MessageListener {
public void onMessage(Message message) {
// TODO validate message using master data cache
}
}
Question: How can I suspend message processing until the startup bean has finished loading the cache?
Any suggestions greatly appreciated :-)!
First i thought inject singleton EJB in mdb would be enough to delay message consumption But no, sometimes it would start consuming the message before @PostConstruct of Singleton-ejb completed. So added a method invocation also and it started working
This worked on glassfish, but i dont see a reason why it shouldnt work on jboss
Singleton-Ejb:
@Singleton
@Startup
public class SingletonBean {
private Logger logger = Logger.getLogger(getClass().getName());
private boolean init = false;
public boolean isInit() {
return init;
}
@PostConstruct
public void init() {
logger.error("singleton init start");
//Do something that takes time here
init = true;
logger.error("singleton init end ");
}
}
and mdb:
@MessageDriven(...)
public class SomeMdb implements MessageListener {
private Logger logger = Logger.getLogger(getClass().getName());
@EJB
SingletonBean sb;
@PostConstruct
public void init() {
logger.error("mdb init start");
if (!sb.isInit()) {
logger.error("never happens");
}
logger.error("mdb init complete");
}
public void onMessage(Message message) {
logger.error("onMessage start");
}
}
Now it always waits for SingletonBean to complete init before mdb completes init (as seen in log)
19:51:51,980 [ad-pool-1; w: 3] ERROR SomeMdb - mdb init start
19:51:52,122 [ad-pool-4848(4)] ERROR SingletonBean - singleton init start
19:51:56,316 [ad-pool-4848(4)] ERROR SingletonBean - singleton init end
19:51:56,317 [ad-pool-1; w: 3] ERROR SomeMdb - mdb init complete
19:51:56,317 [ad-pool-1; w: 3] ERROR SomeMdb - onMessage start
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With