You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quartz调度器中FacesContext.getCurrentInstance()返回null问题排查

问题原因
  • Quartz Job的执行线程是后台调度线程,不属于HTTP请求处理线程,而FacesContext是与当前HTTP请求绑定的对象,仅在处理前端Faces请求时由容器创建,后台线程中不存在该上下文,因此FacesContext.getCurrentInstance()返回null。
  • Omnifaces的Faces.getApplicationAttribute()方法内部依赖FacesContext获取ServletContext,当FacesContext为null时,必然触发空指针异常。
解决方案

无需依赖FacesContext,通过以下两种方式直接获取应用级属性:

方法1:直接注入ServletContext读取属性

利用CDI注入ServletContext,直接读取应用属性:

import java.util.List;
import javax.inject.Inject;
import javax.servlet.ServletContext;
import javax.enterprise.context.ApplicationScoped;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;

@ApplicationScoped
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class DisallowConcurrentQuartzJob implements Job {

    @Inject
    private ServletContext servletContext;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        List<Object> customActionTypeClasses = (List<Object>) servletContext.getAttribute("TEST");
        // 后续业务逻辑
    }
}

方法2:封装为CDI应用级Bean(更规范)

将共享属性封装成@ApplicationScoped的CDI Bean,通过注入直接使用,避免硬编码属性名:

// 定义应用属性Bean
import java.util.List;
import java.util.ArrayList;
import javax.enterprise.context.ApplicationScoped;
import javax.annotation.PostConstruct;

@ApplicationScoped
public class AppProperties {
    private List<Object> test;

    @PostConstruct
    public void init() {
        // 此处初始化属性,比如从配置文件或其他数据源加载
        test = new ArrayList<>();
    }

    public List<Object> getTest() {
        return test;
    }
}

在Quartz Job中注入该Bean:

import java.util.List;
import javax.inject.Inject;
import javax.enterprise.context.ApplicationScoped;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;

@ApplicationScoped
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class DisallowConcurrentQuartzJob implements Job {

    @Inject
    private AppProperties appProperties;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        List<Object> customActionTypeClasses = appProperties.getTest();
        // 后续业务逻辑
    }
}

额外说明

你实现的CDI Job Factory工作正常,已确保Quartz Job能被CDI管理并注入依赖,核心问题是错误地在后台线程中依赖了仅存在于HTTP请求线程的FacesContext。

内容的提问来源于stack exchange,提问作者vished2000

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 08:22:49