views:

404

answers:

1

Hi Guys,

I have created simple example with @Singleton, @Schedule and @Timeout annotations to try if they would solve my problem. The scenario is this: EJB calls 'check' function every 5 secconds, and if certain conditions are met it will create single action timer that would invoke some long running process in asynchronous fashion. (it's sort of queue implementation type of thing). It then continues to check, but as long as long running process is there it won't start another one.

Below is the code I came up with, but this solution does not work, because it looks like asynchronous call I'm making is in fact blocking my @Schedule method.

@Singleton @Startup public class GenerationQueue {

private Logger logger = Logger.getLogger(GenerationQueue.class.getName());

private List<String> queue = new ArrayList<String>();

private boolean available = true;

@Resource
TimerService timerService;

@Schedule(persistent=true, minute="*", second="*/5", hour="*")
public void checkQueueState() {

    logger.log(Level.INFO,"Queue state check: "+available+" size: "+queue.size()+", "+new Date());

    if (available) {

        timerService.createSingleActionTimer(new Date(), new TimerConfig(null, false));
    }

}

@Timeout
private void generateReport(Timer timer) {

    logger.info("!!--timeout invoked here "+new Date());

    available = false;

    try {

        Thread.sleep(1000*60*2); // something that lasts for a bit

    } catch (Exception e) {}

    available = true;

    logger.info("New report generation complete");

}

What am I missing here or should I try different aproach? Any ideas most welcome :)

Testing with Glassfish 3.0.1 latest build - forgot to mention

+1  A: 

The default @ConcurrencyManagement for singletons is ConcurrencyManagementType.CONTAINER with default @Lock of LockType.WRITE. Basically, that means every method (including generateReports) is effectively marked with the synchronized keyword, which means that checkQueueState will block while generateReport is running.

Consider using ConcurrencyManagement(ConcurrencyManagementType.BEAN) or @Lock(LockType.READ). If neither suggestion helps, I suspect you've found a Glassfish bug.

As an aside, you probably want persistent=false since you probably don't need to guarantee that the checkQueueState method fires every 5 seconds even when your server is offline. In other words, you probably don't need the container to fire "catch ups" when you bring your server back online.

bkail
Thanks a lot, the problem was solved by changing concurency to ConcurrencyManagementType.BEAN, and yes, I will change persistent to false :)Thanks for help.
Greg
Nice answer, learned something new. Thanks!
Pascal Thivent