Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Suspend MDB message processing until @StartupBean has finished initialization

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 :-)!

like image 295
skowski Avatar asked Oct 06 '22 03:10

skowski


1 Answers

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
like image 118
Aksel Willgert Avatar answered Oct 10 '22 02:10

Aksel Willgert