Return-Path: X-Original-To: apmail-myfaces-commits-archive@www.apache.org Delivered-To: apmail-myfaces-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 84DB189EE for ; Fri, 9 Sep 2011 16:47:24 +0000 (UTC) Received: (qmail 41448 invoked by uid 500); 9 Sep 2011 16:47:24 -0000 Delivered-To: apmail-myfaces-commits-archive@myfaces.apache.org Received: (qmail 41336 invoked by uid 500); 9 Sep 2011 16:47:23 -0000 Mailing-List: contact commits-help@myfaces.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "MyFaces Development" Delivered-To: mailing list commits@myfaces.apache.org Received: (qmail 41327 invoked by uid 99); 9 Sep 2011 16:47:23 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 09 Sep 2011 16:47:23 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 09 Sep 2011 16:47:20 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id ACF4323889E3 for ; Fri, 9 Sep 2011 16:46:58 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1167285 - /myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java Date: Fri, 09 Sep 2011 16:46:58 -0000 To: commits@myfaces.apache.org From: sobryan@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110909164658.ACF4323889E3@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: sobryan Date: Fri Sep 9 16:46:58 2011 New Revision: 1167285 URL: http://svn.apache.org/viewvc?rev=1167285&view=rev Log: TRINIDAD-195 - Two requests at the same time throw an exception when the server just started *Added some locking code to the GlobalConfigurator Modified: myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java Modified: myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java?rev=1167285&r1=1167284&r2=1167285&view=diff ============================================================================== --- myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java (original) +++ myfaces/trinidad/branches/trinidad-1.2.x/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java Fri Sep 9 16:46:58 2011 @@ -23,8 +23,11 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.ReentrantLock; + import javax.faces.context.ExternalContext; import javax.servlet.ServletRequest; @@ -200,7 +203,7 @@ public final class GlobalConfiguratorImp if (!_isDisabled(ec)) { // If this hasn't been initialized then please initialize - if (!_initialized) + if (!_initialized.get()) { init(ec); } @@ -243,29 +246,38 @@ public final class GlobalConfiguratorImp @Override public void destroy() { - if (_initialized) - { + + if (_initialized.get()) + { try { - for (final Configurator config: _services) + //Forces atomic operations with init. If we are in the middle of an init or another destroy, we'll + //wait on this lock until our operations are complete. We then have to recheck our initialized state. + + _initLock.lock(); + if(_initialized.get()) { - try + for (final Configurator config: _services) { - config.destroy(); - } - catch (final Throwable t) - { - // we always want to continue to destroy things, so log errors and continue - _LOG.severe(t); + try + { + config.destroy(); + } + catch (final Throwable t) + { + // we always want to continue to destroy things, so log errors and continue + _LOG.severe(t); + } } + _services = null; + _initialized.set(false); } - _services = null; - _initialized = false; } finally { //release any managed threadlocals that may have been used durring destroy _releaseManagedThreadLocals(); + _initLock.unlock(); } } } @@ -372,45 +384,54 @@ public final class GlobalConfiguratorImp public void init(ExternalContext ec) { assert ec != null; - - if (!_initialized) + + if (!_initialized.get()) { try { - _services = ClassLoaderUtils.getServices(Configurator.class.getName()); - - // Create a new RequestContextFactory is needed - if (RequestContextFactory.getFactory() == null) + //For thread saftey. It is possible for two threads to enter this code at the same time. When + //the do the second one will wait at the lock until initialization is complete. Then the AtomicBoolean + //is checked again for validity. + _initLock.lock(); + //Check the AtomicBoolean for a change + if(!_initialized.get()) { - RequestContextFactory.setFactory(new RequestContextFactoryImpl()); - } - - // Create a new SkinFactory if needed. - if (SkinFactory.getFactory() == null) - { - SkinFactory.setFactory(new SkinFactoryImpl()); - } - - // register the base skins - SkinUtils.registerBaseSkins(); - - for (final Configurator config: _services) - { - config.init(ec); + _services = ClassLoaderUtils.getServices(Configurator.class.getName()); + + // Create a new RequestContextFactory is needed + if (RequestContextFactory.getFactory() == null) + { + RequestContextFactory.setFactory(new RequestContextFactoryImpl()); + } + + // Create a new SkinFactory if needed. + if (SkinFactory.getFactory() == null) + { + SkinFactory.setFactory(new SkinFactoryImpl()); + } + + // register the base skins + SkinUtils.registerBaseSkins(); + + for (final Configurator config: _services) + { + config.init(ec); + } + + // after the 'services' filters are initialized, then register + // the skin extensions found in trinidad-skins.xml. This + // gives a chance to the 'services' filters to create more base + // skins that the skins in trinidad-skins.xml can extend. + SkinUtils.registerSkinExtensions(ec); + _initialized.set(true); } - - // after the 'services' filters are initialized, then register - // the skin extensions found in trinidad-skins.xml. This - // gives a chance to the 'services' filters to create more base - // skins that the skins in trinidad-skins.xml can extend. - SkinUtils.registerSkinExtensions(ec); - _initialized = true; } finally { //Do cleanup of anything which may have use the thread local manager during //init. _releaseManagedThreadLocals(); + _initLock.unlock(); } } else @@ -483,7 +504,7 @@ public final class GlobalConfiguratorImp context.release(); _releaseManagedThreadLocals(); - + assert RequestContext.getCurrentInstance() == null; } } @@ -500,7 +521,7 @@ public final class GlobalConfiguratorImp resetter.__removeThreadLocals(); } } - + /** * Ensure that all DeferredComponentReferences are fully initialized before the * request completes @@ -727,8 +748,10 @@ public final class GlobalConfiguratorImp private static volatile boolean _sSetRequestBugTested = false; private static boolean _sHasSetRequestBug = false; + + private final ReentrantLock _initLock = new ReentrantLock(); - private boolean _initialized; + private AtomicBoolean _initialized = new AtomicBoolean(false); private List _services; static private final Map _CONFIGURATORS = new HashMap();