JSF initialize application-scope bean when context initialized

前端 未结 3 1853
忘掉有多难
忘掉有多难 2020-12-15 06:55

I\'m building a JSF+Facelets web app, one piece of which is a method that scans a directory every so often and indexes any changes. This method is part of a bean which is i

相关标签:
3条回答
  • 2020-12-15 07:39

    Using listeners or load-on-startup, try this: http://www.thoughtsabout.net/blog/archives/000033.html

    0 讨论(0)
  • 2020-12-15 07:50

    In JSF 2+ you can use a SystemEventListener to handle it. You would set it to take action on the PostConstructApplicationEvent to initialize it.

    <system-event-listener>
        <system-event-listener-class>
         listeners.SystemEventListenerImpl
        </system-event-listener-class>
        <system-event-class>
         javax.faces.event.PostConstructApplicationEvent
        </system-event-class>                       
    </system-event-listener>
    

    The implementation would look something like :

    public class SystemEventListenerImpl implements SystemEventListener {
    
      @Override
      public void processEvent(SystemEvent event) throws AbortProcessingException {
        Application application = (Application) event.getSource();
       //TODO
      }
    
      @Override
      public boolean isListenerForSource(Object source) {
        return (source instanceof Application);
      }
    }
    

    This will allow you to do a lot more than just simply passing a value.

    0 讨论(0)
  • 2020-12-15 08:01

    If your code calls FacesContext, it will not work outside a thread associated with a JSF request lifecycle. A FacesContext object is created for every request and disposed at the end of the request. The reason you can fetch it via a static call is because it is set to a ThreadLocal at the start of the request. The lifecycle of a FacesContext bears no relation to that of a ServletContext.

    Maybe this isn't enough (it sounds like you've already been down this route), but you should be able to use a ServletContextListener to do what you want. Just make sure that any calls to the FacesContext are kept in the JSP's request thread.

    web.xml:

    <listener>
        <listener-class>appobj.MyApplicationContextListener</listener-class>
    </listener>
    

    Implementation:

    public class MyApplicationContextListener implements ServletContextListener {
    
        private static final String FOO = "foo";
    
        public void contextInitialized(ServletContextEvent event) {
            MyObject myObject = new MyObject();
            event.getServletContext().setAttribute(FOO, myObject);
        }
    
        public void contextDestroyed(ServletContextEvent event) {
            MyObject myObject = (MyObject) event.getServletContext().getAttribute(
                    FOO);
            try {
                event.getServletContext().removeAttribute(FOO);
            } finally {
                myObject.dispose();
            }
        }
    
    }
    

    You can address this object via the JSF application scope (or just directly if no other variable exists with the same name):

    <f:view>
        <h:outputText value="#{applicationScope.foo.value}" />
        <h:outputText value="#{foo.value}" />
    </f:view>
    

    If you wish to retrieve the object in a JSF managed bean, you can get it from the ExternalContext:

    FacesContext.getCurrentInstance()
                .getExternalContext().getApplicationMap().get("foo");
    
    0 讨论(0)
提交回复
热议问题