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
相关产品推荐
相关产品推荐

