0

i'm working on a ear java project using Quartz scheduler to schedule several jobs. When deploying my app on the local server I got this kind exception :

11:17:11,775 ERROR [org.quartz.core.JobRunShell] (DefaultQuartzScheduler_Worker-10) Job group2.eventRefundjob threw an unhandled Exception: : org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped
    at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:689)
    at org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:90)
    at org.jboss.weld.bean.ContextualInstanceStrategy$CachingContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:165)
    at org.jboss.weld.bean.ContextualInstance.getIfExists(ContextualInstance.java:63)
    at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:83)
    at org.jboss.weld.bean.proxy.ProxyMethodHandler.getInstance(ProxyMethodHandler.java:125)
    at com.gfp.webservices.apithirdparty.dao.NotificationMessageBrokerDAO$Proxy$_$$_WeldClientProxy.getTotalByMessageType(Unknown Source)
    at com.gfp.webservices.apithirdparty.scheduler.job.AbstractJob.processMessages(AbstractJob.java:49)
    at com.gfp.webservices.apithirdparty.scheduler.job.AbstractJob.execute(AbstractJob.java:43)
    at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)

11:17:11,775 ERROR [org.quartz.core.ErrorLogger] (DefaultQuartzScheduler_Worker-10) Job (group2.eventRefundjob threw an exception.: org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exception: org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped]
    at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped
    at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:689)
    at org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:90)
    at org.jboss.weld.bean.ContextualInstanceStrategy$CachingContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:165)
    at org.jboss.weld.bean.ContextualInstance.getIfExists(ContextualInstance.java:63)
    at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:83)
    at org.jboss.weld.bean.proxy.ProxyMethodHandler.getInstance(ProxyMethodHandler.java:125)
    at com.gfp.webservices.apithirdparty.dao.NotificationMessageBrokerDAO$Proxy$_$$_WeldClientProxy.getTotalByMessageType(Unknown Source)
    at com.gfp.webservices.apithirdparty.scheduler.job.AbstractJob.processMessages(AbstractJob.java:49)
    at com.gfp.webservices.apithirdparty.scheduler.job.AbstractJob.execute(AbstractJob.java:43)
    at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
    ... 1 more

I use Singleton to load the configuration and initialize Jobs

@Singleton
@Startup
public class InitScheduler {

    private Logger log;
    private NotificationMessageBrokerScheduler scheduler;

    public InitScheduler() {
        // default constructor
    }

    @Inject
    public InitScheduler(Logger log, NotificationMessageBrokerScheduler scheduler) {
        this.log = log;
        this.scheduler = scheduler;
    }

    @PostConstruct
    public void initScheduler() throws com.gfp.exceptions.ServiceException {
        log.debug("Construct InitScheduler");
        SchedulerConfiguration.init();
        scheduler.init();
    }

}
@ApplicationScoped
public class SchedulerConfiguration {
// my code 
}

@ApplicationScoped
public class NotificationMessageBrokerScheduler {

    private Logger log;
    private NotificationMessageBrokerDAO notificationMessageBrokerDAO;
    private NotificationService notificationService;
    private NotificationMessageBrokerBuilder notificationMessageBrokerBuilder;
    private NotificationHistoryDao notificationHistoryDao;

public NotificationMessageBrokerScheduler() {
        // default constructor
    }

    @Inject
    public NotificationMessageBrokerScheduler(Logger log, NotificationMessageBrokerDAO notificationMessageBrokerDAO,
            NotificationService notificationService, NotificationMessageBrokerBuilder notificationMessageBrokerBuilder,
            NotificationHistoryDao notificationHistoryDao) {
        super();
        this.log = log;
        this.notificationMessageBrokerDAO = notificationMessageBrokerDAO;
        this.notificationService = notificationService;
        this.notificationMessageBrokerBuilder = notificationMessageBrokerBuilder;
        this.notificationHistoryDao = notificationHistoryDao;
    }

    public void init() {
        log.debug("NotificationMessageBrokerScheduler initiation begin");
        if (canRunScheduler()) {
            try {

                log.debug("EventMessageJob processing");

                JobDetail eventMessageJob = JobBuilder.newJob(EventMessageJob.class)
                        .withIdentity("eventMessageJob", "group1").build();

                eventMessageJob.getJobDataMap().put("log", log);
                eventMessageJob.getJobDataMap().put("notificationMessageBrokerDAO", notificationMessageBrokerDAO);
                eventMessageJob.getJobDataMap().put("notificationService", notificationService);
                eventMessageJob.getJobDataMap().put("notificationMessageBrokerBuilder",
                        notificationMessageBrokerBuilder);

                // shceduled every 5 secondes
                Trigger eventMessageTrigger = TriggerBuilder.newTrigger().withIdentity("eventMessageTrigger", "group1")
                        .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(05).repeatForever())
                        .build();

                log.debug("EventMessageJob created");
                log.debug("EventRefundJob processing");

                JobDetail eventRefundjob = JobBuilder.newJob(EventRefundJob.class)
                        .withIdentity("eventRefundjob", "group2").build();

                eventRefundjob.getJobDataMap().put("log", log);
                eventRefundjob.getJobDataMap().put("notificationMessageBrokerDAO", notificationMessageBrokerDAO);
                eventRefundjob.getJobDataMap().put("notificationService", notificationService);
                eventRefundjob.getJobDataMap().put("notificationMessageBrokerBuilder",
                        notificationMessageBrokerBuilder);

                // shceduled every 60 secondes
                Trigger eventRefundTrigger = TriggerBuilder.newTrigger().withIdentity("eventRefundTrigger", "group2")
                        .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(60).repeatForever())
                        .build();

                log.debug("EventRefundJob created");
                log.debug("PurgeHistoryJob processing");

                JobDetail purgeHistoryJob = JobBuilder.newJob(PurgeHistoryJob.class)
                        .withIdentity("purgeHistoryJob", "group3").build();

                purgeHistoryJob.getJobDataMap().put("log", log);
                purgeHistoryJob.getJobDataMap().put("notificationHistoryDao", notificationHistoryDao);

                // scheduled every days at 7pm
                Trigger purgeHistoryTrigger = TriggerBuilder.newTrigger().withIdentity("purgeHistoryTrigger", "group3")
                        .withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(19, 0)).build();

                log.debug("PurgeHistoryJob created");
                log.debug("FailedNotificationJob processing");

                JobDetail failedNotificationJob = JobBuilder.newJob(FailedNotificationJob.class)
                        .withIdentity("failedNotificationJob", "group4").build();

                failedNotificationJob.getJobDataMap().put("log", log);
                failedNotificationJob.getJobDataMap().put("notificationMessageBrokerDAO", notificationMessageBrokerDAO);
                failedNotificationJob.getJobDataMap().put("notificationService", notificationService);
                failedNotificationJob.getJobDataMap().put("notificationMessageBrokerBuilder",
                        notificationMessageBrokerBuilder);

                // shceduled every 10th minutes of the hour
                Trigger failedNotificationTrigger = TriggerBuilder.newTrigger()
                        .withIdentity("failedNotificationTrigger", "group4")
                        .withSchedule(CronScheduleBuilder.cronSchedule("0 0/10 * * * ?")).build();

                log.debug("FailedNotificationJob created");

                Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
                scheduler.start();

                scheduler.scheduleJob(eventMessageJob, eventMessageTrigger);
                scheduler.scheduleJob(eventRefundjob, eventRefundTrigger);
                scheduler.scheduleJob(purgeHistoryJob, purgeHistoryTrigger);
                scheduler.scheduleJob(failedNotificationJob, failedNotificationTrigger);

                log.debug("NotificationMessageBrokerScheduler initiation done");

            } catch (SchedulerException e) {
                log.error(e.getMessage(), e);
            }
        }
    }

    public boolean canRunScheduler() {
        // Pour que le scheduler s' execute uniquement sur le premier serveur de pool
        try {
            log.debug("NotificicationMessageBrokerScheduler checking servername");
            String serverName = InetAddress.getLocalHost().getHostName();
            log.debug("NotificicationMessageBrokerScheduler server name = " + serverName);
            return (serverName.equalsIgnoreCase(SchedulerConfiguration.getServerName()));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return false;
        }
    }
}

}

Here the abstract job that I use to construct all my jobs

@RequestScoped
public abstract class AbstractJob implements Job {

    protected Logger log;
    protected NotificationMessageBrokerDAO notificationMessageBrokerDAO;
    protected NotificationService notificationService;
    protected NotificationMessageBrokerBuilder notificationMessageBrokerBuilder;

    protected abstract String getMessageType();

    protected abstract int getMaximum();

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDataMap dataMap = context.getJobDetail().getJobDataMap();
        log = (Logger) dataMap.get("log");
        notificationMessageBrokerDAO = (NotificationMessageBrokerDAO) dataMap.get("notificationMessageBrokerDAO");
        notificationService = (NotificationService) dataMap.get("notificationService");
        notificationMessageBrokerBuilder = (NotificationMessageBrokerBuilder) dataMap
                .get("notificationMessageBrokerBuilder");

        processMessages(getMessageType(), getMaximum());

    }

// my code

}

The main service

@Stateless
public class NotificationServiceImpl implements NotificationService {

    private Logger log;
    private SettingsDAO settingsDAO;
    private NotificationHistoryDao notificationHistoryDao;
    private NotificationHistoryBuilder notificationHistoryBuilder;
    private NotificationFCMTokenDAO notificationFCMTokenDAO;

    public NotificationServiceImpl() {
        // defaut constructor
    }

    @Inject
    public NotificationServiceImpl(Logger log, SettingsDAO settingsDAO, NotificationHistoryDao notificationHistoryDao,
            NotificationHistoryBuilder notificationHistoryBuilder, NotificationFCMTokenDAO notificationFCMTokenDAO) {
        this.log = log;
        this.settingsDAO = settingsDAO;
        this.notificationHistoryDao = notificationHistoryDao;
        this.notificationHistoryBuilder = notificationHistoryBuilder;
        this.notificationFCMTokenDAO = notificationFCMTokenDAO;
    }

//my code 
}
@RequestScoped
public class NotificationMessageBrokerDAO extends AbstractDAO {
// my code
}


@RequestScoped
public class NotificationMessageBrokerBuilder {
// my code
}


@RequestScoped
public class NotificationHistoryDao extends AbstractDAO {
//my code
}

I tried to replace all @RequestScoped by @ApplicationScope which seems to work when I deploye for the first time, but If I click on "full publish" to simulate a new deployement on a real server I get the same kind of exception error but this time with application scoped instead of request scope like this

2023-06-30 11:05:44,706 ERROR [org.quartz.core.JobRunShell] (DefaultQuartzScheduler_Worker-5) Job group2.eventRefundjob threw an unhandled Exception: : org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.ApplicationScoped
at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:689)
at org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:90)
at org.jboss.weld.bean.ContextualInstanceStrategy$ApplicationScopedContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:124)
at org.jboss.weld.bean.ContextualInstance.getIfExists(ContextualInstance.java:63)
at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:83)
at org.jboss.weld.bean.proxy.ProxyMethodHandler.getInstance(ProxyMethodHandler.java:125)
at com.gfp.webservices.apithirdparty.dao.NotificationMessageBrokerDAO$Proxy$_$$_WeldClientProxy.getTotalByMessageType(Unknown Source)
at com.gfp.webservices.apithirdparty.scheduler.job.AbstractJob.processMessages(AbstractJob.java:45)
at com.gfp.webservices.apithirdparty.scheduler.job.AbstractJob.execute(AbstractJob.java:39)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)

Something wrong with the scope architecture that I don't understand yet. If someone has any ideas, that would be nice.

  • replaced RequestScoped by ApplicationsScoped
  • replaced ApplicationScoped by Stateless in NotificationMessageBrokerScheduler
  • tried others annotation replacement
  • 1
    Watch out, the `SchedulerConfiguration` is `@ApplicationScoped` (so CDI managed), but you are apparently calling a static init method. This is problematic - maybe unrelated to the question, maybe it won't even manifest, but it is a serious smell. It would be interesting to show how do you initialize Quartz - `scheduler.init()`. Also, JEE offers its own timer mechanism with Message Driven Beans, that is fully integrated with CDI. You may consider giving it a try. – Nikos Paraskevopoulos Jul 05 '23 at 19:47
  • thanks @NikosParaskevopoulos for the advise, i'll consider it asap. I edit the post to show more of my code as you suggest. – Geoffrey Aulombard Jul 06 '23 at 09:10
  • 1
    This surely is weird. Just use `@Schedule`. E.g. https://stackoverflow.com/a/4691650 – BalusC Jul 06 '23 at 12:05
  • What I did in a non-JEE, neither Spring setting that I wanted to use Quartz and have DI working in the jobs was to setup the `Scheduler` with a `JobFactory` that knows how to retrieve the `Job` instances from the DI container, instead of letting Quartz know of the job class and using `new` - like `stdSchedulerFactory = new StdSchedulerFactory(props); scheduler = stdSchedulerFactory.getScheduler(); ...; scheduler.setJobFactory(jobFactory)`. But seriously, try the JEE way (`@Schedule` like BalusC writes), unless you have a very compelling reason to use Quartz directly! – Nikos Paraskevopoulos Jul 07 '23 at 08:08

0 Answers0