http://java.net/jira/browse/JAVASERVERFACES-11984 SECTION: Modified Files ---------------------------- M jsf-ri/test/com/sun/faces/renderkit/TestRenderKit.java remove attr Application from servletContext M jsf-ri/test/com/sun/faces/application/TestApplicationFactoryImpl.java NPE will not be thrown so change the assertion. M jsf-ri/test/com/sun/faces/config/ConfigureListenerTestCase.java clear Application from the externalcontext M jsf-ri/src/main/java/com/sun/faces/application/ApplicationAssociate.java M jsf-ri/src/main/java/com/sun/faces/application/ApplicationFactoryImpl.java removed the application field. It should not be saved since we need one per servletcontext. M jsf-ri/src/main/java/com/sun/faces/application/ApplicationImpl.java M jsf-ri/src/main/java/com/sun/faces/application/InjectionApplicationFactory.java M jsf-ri/src/main/java/com/sun/faces/config/processor/FactoryConfigProcessor.java check for application and applicationassociate for null values after the factory has been found M jsf-ri/src/main/java/com/sun/faces/config/ConfigureListener.java SECTION: Diffs ---------------------------- Index: jsf-ri/test/com/sun/faces/renderkit/TestRenderKit.java =================================================================== --- jsf-ri/test/com/sun/faces/renderkit/TestRenderKit.java (revision 8758) +++ jsf-ri/test/com/sun/faces/renderkit/TestRenderKit.java (working copy) @@ -470,6 +470,7 @@ ServletContext servletContext = (ServletContext) ctx.getExternalContext().getContext(); FactoryFinder.releaseFactories(); servletContext.removeAttribute("com.sun.faces.ApplicationAssociate"); + servletContext.removeAttribute("com.sun.faces.application.ApplicationImpl"); ConfigManager config = ConfigManager.getInstance(); DocumentBuilderFactory factory = DbfFactory.getFactory(); Index: jsf-ri/test/com/sun/faces/application/TestApplicationFactoryImpl.java =================================================================== --- jsf-ri/test/com/sun/faces/application/TestApplicationFactoryImpl.java (revision 8758) +++ jsf-ri/test/com/sun/faces/application/TestApplicationFactoryImpl.java (working copy) @@ -136,7 +136,7 @@ } catch (NullPointerException e) { thrown = true; } - assertTrue(thrown); + assertFalse(thrown); } Index: jsf-ri/test/com/sun/faces/config/ConfigureListenerTestCase.java =================================================================== --- jsf-ri/test/com/sun/faces/config/ConfigureListenerTestCase.java (revision 8758) +++ jsf-ri/test/com/sun/faces/config/ConfigureListenerTestCase.java (working copy) @@ -133,6 +133,7 @@ import com.sun.faces.cactus.ServletFacesTestCase; import com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter; import com.sun.faces.application.ApplicationAssociate; +import com.sun.faces.application.ApplicationImpl; import junit.framework.Test; import junit.framework.TestSuite; @@ -254,6 +255,7 @@ ServletContext ctx = (ServletContext) getFacesContext().getExternalContext().getContext(); ApplicationAssociate.clearInstance(getFacesContext().getExternalContext()); + ApplicationImpl.clearInstance(getFacesContext().getExternalContext()); ctx.removeAttribute("com.sun.faces.config.WebConfiguration"); ServletContextWrapper w = new ServletContextWrapper(ctx); ServletContextEvent sce = new ServletContextEvent(w); @@ -297,6 +299,7 @@ ServletContext ctx = (ServletContext) getFacesContext().getExternalContext().getContext(); ApplicationAssociate.clearInstance(getFacesContext().getExternalContext()); + ApplicationImpl.clearInstance(getFacesContext().getExternalContext()); ctx.removeAttribute("com.sun.faces.config.WebConfiguration"); ServletContextWrapper w = new ServletContextWrapper(ctx); ServletContextEvent sce = new ServletContextEvent(w); Index: jsf-ri/src/main/java/com/sun/faces/application/ApplicationAssociate.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/application/ApplicationAssociate.java (revision 8758) +++ jsf-ri/src/main/java/com/sun/faces/application/ApplicationAssociate.java (working copy) @@ -91,6 +91,9 @@ import javax.faces.application.ProjectStage; import javax.faces.event.PreDestroyCustomScopeEvent; import javax.faces.event.ScopeContext; +import javax.faces.application.ApplicationWrapper; +import javax.faces.application.ApplicationFactory; +import javax.faces.application.Application; import javax.servlet.ServletContext; import java.util.Collections; @@ -138,7 +141,7 @@ // Flag indicating that a response has been rendered. private boolean responseRendered = false; - private static final String ASSOCIATE_KEY = RIConstants.FACES_PREFIX + + public static final String ASSOCIATE_KEY = RIConstants.FACES_PREFIX + "ApplicationAssociate"; private static ThreadLocal instance = Index: jsf-ri/src/main/java/com/sun/faces/application/ApplicationFactoryImpl.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/application/ApplicationFactoryImpl.java (revision 8758) +++ jsf-ri/src/main/java/com/sun/faces/application/ApplicationFactoryImpl.java (working copy) @@ -49,6 +49,7 @@ import javax.faces.application.Application; import javax.faces.application.ApplicationFactory; +import javax.faces.context.FacesContext; /** *

ApplicationFactory is a factory object that creates @@ -66,31 +67,12 @@ // Log instance for this class private static final Logger logger = FacesLogger.APPLICATION.getLogger(); - // - // Protected Constants - // - // - // Class Variables - // - - // Attribute Instance Variables - - private volatile Application application; - - // Relationship Instance Variables - - // - // Constructors and Initializers - // - - /* * Constructor */ public ApplicationFactoryImpl() { super(); - application = null; if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Created ApplicationFactory "); } @@ -102,7 +84,8 @@ * for this web application.

*/ public Application getApplication() { - + Application application = + (Application)FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().get(ApplicationImpl.class.getName()); if (application == null) { application = new ApplicationImpl(); if (logger.isLoggable(Level.FINE)) { @@ -113,7 +96,7 @@ return application; } - + /** *

Replace the {@link Application} instance that will be * returned for this web application.

@@ -121,16 +104,19 @@ * @param application The replacement {@link Application} instance */ public synchronized void setApplication(Application application) { - if (application == null) { - String message = MessageUtils.getExceptionMessageString - (MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "application"); - throw new NullPointerException(message); +// if (application == null) { +// String message = MessageUtils.getExceptionMessageString +// (MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "application"); +// throw new NullPointerException(message); +// } + if (application != null) { + FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().put(ApplicationImpl.class.getName(), application); + FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().put(ApplicationAssociate.ASSOCIATE_KEY, + ((com.sun.faces.application.ApplicationImpl) application).getApplicationAssociate()); + if (logger.isLoggable(Level.FINE)) { + logger.fine(MessageFormat.format("set Application Instance to ''{0}''", + application.getClass().getName())); + } } - - this.application = application; - if (logger.isLoggable(Level.FINE)) { - logger.fine(MessageFormat.format("set Application Instance to ''{0}''", - application.getClass().getName())); - } } } Index: jsf-ri/src/main/java/com/sun/faces/application/ApplicationImpl.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/application/ApplicationImpl.java (revision 8758) +++ jsf-ri/src/main/java/com/sun/faces/application/ApplicationImpl.java (working copy) @@ -40,6 +40,7 @@ package com.sun.faces.application; +import javax.servlet.ServletContext; import java.beans.PropertyEditor; import java.beans.PropertyEditorManager; import java.lang.reflect.Constructor; @@ -76,6 +77,7 @@ import javax.faces.component.UIViewRoot; import javax.faces.component.behavior.Behavior; import javax.faces.context.FacesContext; +import javax.faces.context.ExternalContext; import javax.faces.convert.Converter; import javax.faces.convert.DateTimeConverter; import javax.faces.el.MethodBinding; @@ -234,7 +236,23 @@ } } + /** + * method to return the ApplicationAssociate instance + * @return associate + */ + public ApplicationAssociate getApplicationAssociate() { + return associate; + } + public static void clearInstance(ServletContext sc) { + sc.removeAttribute(ApplicationImpl.class.getName()); + } + + public static void clearInstance(ExternalContext sc) { + sc.getApplicationMap().remove(ApplicationImpl.class.getName()); + } + + /** * @see javax.faces.application.Application#publishEvent(FacesContext, Class, Object) */ Index: jsf-ri/src/main/java/com/sun/faces/application/InjectionApplicationFactory.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/application/InjectionApplicationFactory.java (revision 8758) +++ jsf-ri/src/main/java/com/sun/faces/application/InjectionApplicationFactory.java (working copy) @@ -65,11 +65,7 @@ private static final Logger LOGGER = FacesLogger.APPLICATION.getLogger(); private ApplicationFactory delegate; - private Application defaultApplication; - private Field defaultApplicationField; - private volatile Application application; - - + // ------------------------------------------------------------ Constructors @@ -85,18 +81,18 @@ public Application getApplication() { - + + Application application = delegate.getApplication(); if (application == null) { - application = delegate.getApplication(); - if (application == null) { - // No i18n here + // No i18n here String message = MessageFormat .format("Delegate ApplicationContextFactory, {0}, returned null when calling getApplication().", - delegate.getClass().getName()); - throw new IllegalStateException(message); - } - injectDefaultApplication(); + delegate.getClass().getName()); + throw new IllegalStateException(message); } + + injectDefaultApplication(application); + return application; } @@ -104,9 +100,10 @@ public synchronized void setApplication(Application application) { - this.application = application; - delegate.setApplication(application); - injectDefaultApplication(); + if (application != null) { + delegate.setApplication(application); + injectDefaultApplication(application); + } } @@ -125,25 +122,19 @@ // --------------------------------------------------------- Private Methods - private void injectDefaultApplication() { + private void injectDefaultApplication(Application application) { + Application defaultApplication; + Field defaultApplicationField; + FacesContext ctx = FacesContext.getCurrentInstance(); + String attrName = ApplicationImpl.class.getName(); + defaultApplication = (Application) ctx.getExternalContext().getApplicationMap().get(attrName); - if (defaultApplication == null) { - FacesContext ctx = FacesContext.getCurrentInstance(); - String attrName = ApplicationImpl.class.getName(); - defaultApplication = (Application) ctx.getExternalContext() - .getApplicationMap().get(attrName); - ctx.getExternalContext().getApplicationMap() - .remove(attrName); - } if (defaultApplication != null) { try { - if (defaultApplicationField == null) { - defaultApplicationField = - Application.class - .getDeclaredField("defaultApplication"); - defaultApplicationField.setAccessible(true); - } + defaultApplicationField = + Application.class.getDeclaredField("defaultApplication"); + defaultApplicationField.setAccessible(true); defaultApplicationField.set(application, defaultApplication); } catch (NoSuchFieldException nsfe) { Index: jsf-ri/src/main/java/com/sun/faces/config/processor/FactoryConfigProcessor.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/config/processor/FactoryConfigProcessor.java (revision 8758) +++ jsf-ri/src/main/java/com/sun/faces/config/processor/FactoryConfigProcessor.java (working copy) @@ -40,6 +40,10 @@ package com.sun.faces.config.processor; +import com.sun.faces.application.ApplicationAssociate; +import javax.faces.application.Application; +import javax.faces.application.ApplicationFactory; +import javax.faces.context.FacesContext; import com.sun.faces.config.ConfigurationException; import com.sun.faces.config.DocumentInfo; import com.sun.faces.util.FacesLogger; @@ -202,7 +206,7 @@ applicationFactoryCount); } } - + // If there are more than one ApplicationFactory, FacesContextFactory, // or ExternalContextFactory defined, we will push our Injection // factories onto the factory list so that they are the top-level @@ -217,6 +221,17 @@ // validate that we actually have factories at this point. verifyFactoriesExist(); + if (FacesContext.getCurrentInstance() != null && + FacesContext.getCurrentInstance().getExternalContext() != null) { + ApplicationAssociate associate = + ApplicationAssociate.getInstance( + FacesContext.getCurrentInstance().getExternalContext()); + ApplicationFactory afactory = (ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY); + Application app = afactory.getApplication(); + if (app != null && associate == null) { + afactory.setApplication(null); + } + } // invoke the next config processor invokeNext(sc, documentInfos); @@ -241,6 +256,8 @@ appCount.incrementAndGet(); setFactory(FactoryFinder.APPLICATION_FACTORY, getNodeText(n)); + + } else if (EXCEPTION_HANDLER_FACTORY.equals(n.getLocalName())) { setFactory(FactoryFinder.EXCEPTION_HANDLER_FACTORY, getNodeText(n)); Index: jsf-ri/src/main/java/com/sun/faces/config/ConfigureListener.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/config/ConfigureListener.java (revision 8758) +++ jsf-ri/src/main/java/com/sun/faces/config/ConfigureListener.java (working copy) @@ -223,7 +223,9 @@ Verifier.setCurrentInstance(new Verifier()); } initScripting(); + configManager.initialize(context); + if (shouldInitConfigMonitoring()) { initConfigMonitoring(context); } @@ -344,6 +346,7 @@ } finally { ApplicationAssociate.clearInstance(context); ApplicationAssociate.setCurrentInstance(null); + com.sun.faces.application.ApplicationImpl.clearInstance(context); // Release the initialization mark on this web application ConfigManager.getInstance().destory(context); if (initContext != null) {