【问题标题】:Is it possible to reference FacesContext from a TimerTask or ScheduledExecutorService on application startup?是否可以在应用程序启动时从 TimerTask 或 ScheduledExecutorService 引用 FacesContext?
【发布时间】:2012-01-15 09:43:52
【问题描述】:

我正在尝试在 JSF1.2/ADF Web 应用程序中创建功能,该应用程序将定期动态地为一个网站生成站点地图,该网站将有数百个页面,其内容每天都会发生变化。问题是我需要从应用程序中读取一些配置以用作站点地图的基础,为此,我需要 FacesContext。

这是我尝试做的事情:我创建了一个实现 ServletContextListener 并实例化应用程序范围 bean 的类。这个 bean 使用 FacesContext 完成繁重的工作来创建 sitemap.xml。我创建了一个扩展 TimerTask 的类,该类从应用程序范围访问 bean,调用站点地图方法并安排未来的发生。当我运行应用程序时,实现 ServletContextListener 的类触发并且 bean 似乎已创建,但扩展 TimerTask 的类从未触发。任何帮助,将不胜感激。如果我能回答任何问题或遗漏了什么,请告诉我。

这是我的代码示例:

public class WebhomesApplicationContextListener implements ServletContextListener {
 private static final String attribute = "SiteMapGenerator";
  public void contextInitialized(ServletContextEvent event) {
  SiteMapGenerator myObject = new SiteMapGenerator();
  event.getServletContext().setAttribute(attribute, myObject);
 }
 public void contextDestroyed(ServletContextEvent event) {
  SiteMapGenerator myObject = (SiteMapGenerator) event.getServletContext().getAttribute(attribute);
  event.getServletContext().removeAttribute(attribute);
 }
}

public class SiteMapGenerator {
 public void generateSitemap() {
   // code to generate map...
 }
}

public class Scheduler extends TimerTask {
 public void run() {
  SiteMapGenerator sitemap = (SiteMapGenerator)FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().get("SiteMapGenerator");
  sitemap.generateSitemap();
 }
}

class MainApplication {
 public static void main(String[] args) {
  Timer timer = new Timer();
  timer.schedule(
   new Scheduler(),
   1000 * 60);
 }
}

【问题讨论】:

    标签: jsf jdeveloper facescontext


    【解决方案1】:

    不,你不能。 FacesContext 仅在与 URL 与 FacesServlet 的 URL 模式匹配并已调用它的 HTTP servlet 请求关联的线程中可用。相反,只需将SiteMapGenerator 传递给Scheduler 即可。

    public class Scheduler {
    
        private SiteMapGenerator sitemap;
    
        public Scheduler(SiteMapGenerator sitemap) {
            this.sitemap = sitemap;
        }
    
        // ...
    }
    

    SiteMapGenerator 在您构建Scheduler 时肯定可用。


    与具体问题无关,强烈建议不要在 Java EE 应用程序中使用 TimerTask。另见Spawning threads in a JSF managed bean for scheduled tasks using a timer

    【讨论】:

    • 感谢链接,今天下午实际上正在查看它以切换到 ScheduledExecutorService。鉴于您的回复,我不确定如何/何时构建调度程序,因为我需要在部署时自动启用它。
    • 链接中有例子。您只需要 XML 而不是注释来注册应用程序范围的 bean 或 servlet 上下文侦听器。
    • 也许我的 Java 新手在这方面阻碍了我......使用您提供的链接中的示例,我创建了一个“BackgroundJobManager”应用程序范围的 bean,它在其实例化“SomeDailyJob”类init() 方法。在应用程序加载时,不触发 BackgroundJobManager init() 方法。由于 ServletContextListener 不是一个选项,我很难理解如何让“BackgroundJobManager”在应用程序启动时进行处理。这是我的sample code
    • 在 JSF 1.x 中,您将需要将此应用程序范围的 bean 引用为某个公共请求或会话范围 bean 的托管属性,或者可能在某个公共视图模板中。顺便说一句,为什么ServletContextListener 不是一个选项?
    • 感谢您在这方面的持续帮助。由于我最初的失败和我对您答案的解释,我认为 ServletContextListener 不是一个选项。因此,例如,通过“将此应用程序范围的 bean 引用为某个公共请求或会话范围 bean 的托管属性,或者可能在某个公共视图模板中”,例如,我可以在主页视图的 beforePhase 方法中调用该 bean。由于我不希望它每次都触发,似乎我必须进行检查,以便每次用户点击主页时都不会调用它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-01
    • 2019-11-23
    • 2012-05-09
    • 1970-01-01
    • 2016-01-08
    • 1970-01-01
    相关资源
    最近更新 更多