2015-01-12 43 views
1

問題是ApplicationScoped bean被初始化很多次。在它穩定到頁面使用的穩定bean之前。 如果使用應用程序範圍預加載配置並進行驗證。 有一個過濾器,如果任何驗證失敗,它將進入「修復配置」頁面。在ServletContextListener中使用CDI多次初始化JSF ApplicationScoped Bean

我有一個ServletContextInitlizer

import javax.inject.Inject; 
import javax.servlet.ServletContextListener; 
import org.apache.logging.log4j.LogManager; 
import org.apache.logging.log4j.Logger; 

public class StartupContextListener implements ServletContextListener { 
    Logger logger = LogManager.getLogger(StartupContextListener.class.getName()); 
    @Inject 
    private BaseConfiguration baseConfiguration; 

    public StartupContextListener() { 
     super(); 
    } 

    @Override 
    public void contextInitialized(ServletContextEvent sce) { 
     logger.info("contextInitialized"); 
     try {  
      // Validate data directory 
      baseConfiguration.getConfigPathFile(); // it validates 
      //other validations 
     } catch (Throwable t) { 
      baseConfiguration.invalidateApplication("Application startup validation failed "+ t.getMessage(), t); 
     } 
     logger.info("Application started."); 
    } 

    @Override 
    public void contextDestroyed(ServletContextEvent sce) { 
     logger.info("Redtape application shutting down....."); 
    } 
} 

@ManagedBean(name="baseConfiguration",eager=true) 
@ApplicationScoped 
public class BaseConfiguration {  

    private File dataDirectory = null; 
    private boolean validConfiguration=true; 
    private String configurationMessage=null; 

    Logger logger = LogManager.getLogger(BaseConfiguration.class.getName()); 

    public BaseConfiguration() { 
     super();   
     logger.info(**"BaseConfiguration is CONSTRUCTED."**); 
    } 
    public String getConfigurationMessage() { 
     return configurationMessage; 
    } 
    public boolean isValidConfiguration() { 
     return validConfiguration; 
    } 
    public void invalidateApplication(String message,Throwable t) { 
     this.validConfiguration=false; 
     this.configurationMessage=message; 
     logger.fatal(message,t); 
    } 

    private String getConfigPathString() {  
     try { 
      logger.info("Loading ["+BASE_PROPERTIES_FILE+"] file."); 
      //validates a a configuration file 
     } catch (IOException e) {   
      invalidateApplication("Unabled to load ["+BASE_PROPERTIES_FILE+"] from classpath.",e); 
      return null; 
     } 
    } 
} 

Maven的依賴關係是

<properties> 
    <weld.version>1.1.9.Final</weld.version> 
    <weld.version></weld.version> 
</properties> 

<dependencies> 
    <dependency> 
     <groupId>org.glassfish.web</groupId> 
     <artifactId>el-impl</artifactId> 
     <version>2.2</version> 
    </dependency> 
    <dependency> 
     <groupId>com.sun.faces</groupId> 
     <artifactId>jsf-api</artifactId> 
     <version>2.2.5</version> 
    </dependency> 
    <dependency> 
     <groupId>com.sun.faces</groupId> 
     <artifactId>jsf-impl</artifactId> 
     <version>2.2.5</version> 
    </dependency> 
    <dependency> 
     <groupId>javax.servlet</groupId> 
     <artifactId>javax.servlet-api</artifactId> 
     <version>3.1.0</version> 
    </dependency> 
    <dependency> 
     <groupId>org.primefaces</groupId> 
     <artifactId>primefaces</artifactId> 
     <version>5.1</version> 
    </dependency> 
    <dependency> 
     <groupId>javax.servlet</groupId> 
     <artifactId>jstl</artifactId> 
     <version>1.2</version> 
    </dependency> 
    <dependency> 
     <groupId>javax.servlet</groupId> 
     <artifactId>servlet-api</artifactId> 
     <version>2.5</version> 
    </dependency> 
    <dependency> 
     <groupId>javax.servlet.jsp</groupId> 
     <artifactId>javax.servlet.jsp-api</artifactId> 
     <version>2.3.1</version> 
    </dependency> 
    <dependency> 
     <groupId>dk.heick.jhpropertiestyped</groupId> 
     <artifactId>jhpropertiestyped</artifactId> 
     <version>1.9</version> 
    </dependency> 
    <dependency> 
     <groupId>org.primefaces.themes</groupId> 
     <artifactId>all-themes</artifactId> 
     <version>1.0.10</version> 
    </dependency> 
    <dependency> 
     <groupId>org.apache.logging.log4j</groupId> 
     <artifactId>log4j-api</artifactId> 
     <version>2.1</version> 
    </dependency> 
    <dependency> 
     <groupId>org.apache.logging.log4j</groupId> 
     <artifactId>log4j-core</artifactId> 
     <version>2.1</version> 
    </dependency> 
    <dependency> 
     <groupId>org.apache.logging.log4j</groupId> 
     <artifactId>log4j-web</artifactId> 
     <version>2.1</version> 
     <scope>runtime</scope> 
    </dependency> 
    <dependency> 
     <groupId>org.jboss.weld.servlet</groupId> 
     <artifactId>weld-servlet</artifactId> 
     <version>3.0.0.Alpha1</version> 
    </dependency> 
</dependencies> 

我在日誌中看到什麼。 我得到3到5個構造函數已被調用。尋找「BaseConfiguration是CONSTRUCTED」。下面。

jan. 12, 2015 6:28:39 PM org.jboss.weld.environment.servlet.EnhancedListener onStartup 
INFO: WELD-ENV-001008: Initialize Weld using ServletContainerInitializer 
jan. 12, 2015 6:28:40 PM org.jboss.weld.bootstrap.WeldStartup <clinit> 
INFO: WELD-000900: 3.0.0 (Alpha1) 
jan. 12, 2015 6:28:40 PM org.jboss.weld.environment.servlet.deployment.WebAppBeanArchiveScanner scan 
WARN: WELD-ENV-001004: Found both WEB-INF/beans.xml and WEB-INF/classes/META-INF/beans.xml. It's not portable to use both locations at the same time. Weld is going to use file:/C:/Users/Frederik/Dropbox/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp3/wtpwebapps/dk.ionit.redtape.Redtape-1.0/WEB-INF/beans.xml. 
jan. 12, 2015 6:28:40 PM org.jboss.weld.bootstrap.WeldStartup startContainer 
INFO: WELD-000101: Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously. 
jan. 12, 2015 6:28:41 PM org.jboss.weld.interceptor.util.InterceptionTypeRegistry <clinit> 
WARN: WELD-001700: Interceptor annotation class javax.ejb.PostActivate not found, interception based on it is not enabled 
jan. 12, 2015 6:28:41 PM org.jboss.weld.interceptor.util.InterceptionTypeRegistry <clinit> 
WARN: WELD-001700: Interceptor annotation class javax.ejb.PrePassivate not found, interception based on it is not enabled 
jan. 12, 2015 6:28:41 PM org.jboss.weld.environment.tomcat.TomcatContainer initialize 
INFO: WELD-ENV-001100: Tomcat 7+ detected, CDI injection will be available in Servlets, Filters and Listeners. 
20150112 18:28:42.758 [localhost-startStop-1] WARN dk.BaseConfiguration - BaseConfiguration is CONSTRUCTED. 
"This is where it is constructed"........ 
    at dk.BaseConfiguration.<init>(BaseConfiguration.java:32) [BaseConfiguration.class:?] 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_05] 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) [?:1.8.0_05] 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) [?:1.8.0_05] 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:408) [?:1.8.0_05] 
    at org.jboss.weld.injection.ConstructorInjectionPoint.newInstance(ConstructorInjectionPoint.java:113) [weld-servlet-3.0.0.Alpha1.jar:2014-10-01 17:10] 
    ...... 
jan. 12, 2015 6:28:42 PM com.sun.faces.config.ConfigureListener contextInitialized 
INFO: Initializing Mojarra 2.2.5 (20140108-1427 https://svn.java.net/svn/mojarra~svn/tags/[email protected]) for context '/Redtape' 
jan. 12, 2015 6:28:43 PM com.sun.faces.spi.InjectionProviderFactory createInstance 
INFO: JSF1048: PostConstruct/PreDestroy annotations present. ManagedBeans methods marked with these annotations will have said annotations processed. 
jan. 12, 2015 6:28:44 PM com.sun.faces.config.ConfigureListener$WebConfigResourceMonitor$Monitor <init> 
INFO: Monitoring file:/C:/Users/Frederik/Dropbox/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp3/wtpwebapps/dk.MyApp-1.0/WEB-INF/faces-config.xml for modifications 
20150112 18:28:45.025 [localhost-startStop-1] WARN dk..BaseConfiguration - BaseConfiguration is CONSTRUCTED. 
"This is where it is constructed"........ 
    at dk.BaseConfiguration.<init>(BaseConfiguration.java:32) [BaseConfiguration.class:?] 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_05] 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) [?:1.8.0_05] 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) [?:1.8.0_05] 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:408) [?:1.8.0_05] 
    at java.lang.Class.newInstance(Class.java:433) [?:1.8.0_05] 
    at com.sun.faces.mgbean.BeanBuilder.newBeanInstance(BeanBuilder.java:186) [jsf-impl-2.2.5.jar:2.2.5]  
    ....... 
jan. 12, 2015 6:28:45 PM org.primefaces.webapp.PostConstructApplicationEventListener processEvent 
INFO: Running on PrimeFaces 5.1 
jan. 12, 2015 6:28:45 PM org.jboss.weld.environment.servlet.Listener contextInitialized 
INFO: WELD-ENV-001006: org.jboss.weld.environment.servlet.EnhancedListener used for ServletContext notifications 
20150112 18:28:45.087 [localhost-startStop-1] INFO dk.ionit.redtape.system.StartupContextListener - contextInitialized 
20150112 18:28:45.087 [localhost-startStop-1] INFO dk.ionit.redtape.system.StartupContextListener - Application starting..... 
20150112 18:28:45.089 [localhost-startStop-1] INFO dk.ionit.redtape.system.StartupContextListener - Application started. 
jan. 12, 2015 6:28:45 PM com.sun.faces.config.ConfigureListener contextInitialized 
INFO: Initializing Mojarra 2.2.5 (20140108-1427 https://svn.java.net/svn/mojarra~svn/tags/[email protected]) for context '/Redtape' 
jan. 12, 2015 6:28:45 PM com.sun.faces.spi.InjectionProviderFactory createInstance 
INFO: JSF1048: PostConstruct/PreDestroy annotations present. ManagedBeans methods marked with these annotations will have said annotations processed. 
20150112 18:28:45.528 [localhost-startStop-1] WARN dk.BaseConfiguration - BaseConfiguration is CONSTRUCTED. 
java.lang.Exception 
    at dk..BaseConfiguration.<init>(BaseConfiguration.java:32) [BaseConfiguration.class:?] 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_05] 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) [?:1.8.0_05] 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) [?:1.8.0_05] 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:408) [?:1.8.0_05] 
    at java.lang.Class.newInstance(Class.java:433) [?:1.8.0_05] 
    at com.sun.faces.mgbean.BeanBuilder.newBeanInstance(BeanBuilder.java:186) [jsf-impl-2.2.5.jar:2.2.5]  
    ....... 
20150112 18:28:45.529 [localhost-startStop-1] WARN dk.ionit.redtape.system.BaseConfiguration - BaseConfiguration is CONSTRUCTED. 
java.lang.Exception 
    at dk..BaseConfiguration.<init>(BaseConfiguration.java:32) [BaseConfiguration.class:?] 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_05] 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) [?:1.8.0_05] 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) [?:1.8.0_05] 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:408) [?:1.8.0_05] 
    at java.lang.Class.newInstance(Class.java:433) [?:1.8.0_05] 
    at com.sun.faces.mgbean.BeanBuilder.newBeanInstance(BeanBuilder.java:186) [jsf-impl-2.2.5.jar:2.2.5] 
    ....... 
jan. 12, 2015 6:28:45 PM org.primefaces.webapp.PostConstructApplicationEventListener processEvent 
INFO: Running on PrimeFaces 5.1 
jan. 12, 2015 6:28:45 PM org.primefaces.webapp.PostConstructApplicationEventListener processEvent 
INFO: Running on PrimeFaces 5.1 
jan. 12, 2015 6:28:45 PM org.jboss.weld.environment.servlet.EnhancedListener contextInitialized 
INFO: WELD-ENV-001009: org.jboss.weld.environment.servlet.Listener used for ServletRequest and HttpSession notifications 
20150112 18:28:45.537 [localhost-startStop-1] WARN dk.ionit.redtape.system.BaseConfiguration - BaseConfiguration is CONSTRUCTED. 
java.lang.Exception 
    at dk..BaseConfiguration.<init>(BaseConfiguration.java:32) [BaseConfiguration.class:?] 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_05] 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) [?:1.8.0_05] 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) [?:1.8.0_05] 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:408) [?:1.8.0_05] 
    at org.jboss.weld.injection.ConstructorInjectionPoint.newInstance(ConstructorInjectionPoint.java:113) [weld-servlet-3.0.0.Alpha1.jar:2014-10-01 17:10] 
    ....... 
jan. 12, 2015 6:28:45 PM org.apache.coyote.AbstractProtocol start 
INFO: Starting ProtocolHandler ["http-nio-8080"] 
jan. 12, 2015 6:28:45 PM org.apache.coyote.AbstractProtocol start 
INFO: Starting ProtocolHandler ["ajp-nio-8009"] 
jan. 12, 2015 6:28:45 PM org.apache.catalina.startup.Catalina start 
INFO: Server startup in 10658 ms 

的問題是:

我如何有一個ApplicationScope託管bean,這是隻加載一次,可以通過EL或CDI,這是一次構造在ServletContectListener在JSF上下文的訪問。???????

THX提前 「與Insigth專家」

+0

你是怎麼想到注射JSF中使用CDI神器'@ Inject'一個'ServletContextListener'託管Bean('BaseConfiguration')的?這甚至工作嗎? – Tiny

回答

2

您正在使用CDI注入,所以你應該使用

@Named 
@ApplicationScoped 

後者從javax.enterprise.context包!

而且,你不應該依賴於構造的管理豆類,使用這樣的方法:

@PostConstruct 
public void init() { 
... 
} 

這將被調用一次,因爲你所期望的。

+0

OP寫道:「我如何擁有一個ApplicationScope託管bean,它只能加載ONCE並且可以通過EL或CDI訪問......」我不明白ServletContextListener部分。 – szegedi

0

@你是對的 - 爲什麼即使使用ServletContextListener,當你的ApplicationScoped bean已經初始化validated/context。 我的問題是我的上下文被初始化了4次。

的解決方案是,我已經使用

@ javax.faces.bean ...註釋

,而不是

@ javax.enterprise.context ...註釋

看到一個很好的描述

http://germanescobar.net/2010/04/4-areas-of-possible-confusion-in-jee6.html

好@szegedi指出了我。 .-)

回到你的觀點,如果我們有一個ApplicationScoped bean,我們不需要ServletContext。

只需使用:

import javax.annotation.PostConstruct; 
    import javax.inject.Named; 
    import javax.enterprise.context.ApplicationScoped; 

    import org.apache.logging.log4j.LogManager; 
    import org.apache.logging.log4j.Logger; 


    @Named 
    @ApplicationScoped 
    public class BaseConfiguration { 
     @PostConstruct 
      public void init() {  
       logger.info("BaseConfiguration is CONSTRUCTED."); 
       //do init stuff as in ServletContextListener 
      } 
    } 
} 
相關問題