Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 228646 Details for
Bug 403628
Asynchronous context shutdown causes timeouts during LifecycleManager#maybeCloseApplicationContextFor(Bundle) in Apache Felix
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read
this important communication.
[patch]
Patch for the extenderConfiguration and LifecycleManager to make asynchronous context shutdown configurable. Includes Documentation and LifecycleManager testcase.
403628-against-master.patch (text/plain), 19.90 KB, created by
Olaf Otto
on 2013-03-19 11:09:42 EDT
(
hide
)
Description:
Patch for the extenderConfiguration and LifecycleManager to make asynchronous context shutdown configurable. Includes Documentation and LifecycleManager testcase.
Filename:
MIME Type:
Creator:
Olaf Otto
Created:
2013-03-19 11:09:42 EDT
Size:
19.90 KB
patch
obsolete
>From 1f3a795c8eb9a421857989213e33b2923437ff4e Mon Sep 17 00:00:00 2001 >From: "olaf.otto" <olaf.otto@unic.com> >Date: Mon, 18 Mar 2013 18:52:06 +0100 >Subject: [PATCH 1/3] 403628: Asynchronous context shutdown causes timeouts > during > LifecycleManager#maybeCloseApplicationContextFor(Bundle) > in Apache Felix > (https://bugs.eclipse.org/bugs/show_bug.cgi?id=403628) > >--- > .../internal/activator/LifecycleManager.java | 28 ++++++++++------- > .../internal/support/ExtenderConfiguration.java | 35 +++++++++++++++++++--- > .../ExtenderConfigurationCustomSettingsTest.java | 6 +++- > .../ExtenderConfigurationDefaultSettingsTest.java | 6 +++- > .../internal/support/extender-custom-config.xml | 1 + > 5 files changed, 59 insertions(+), 17 deletions(-) > >diff --git a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManager.java b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManager.java >index b2d5e43..a43bcab 100644 >--- a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManager.java >+++ b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManager.java >@@ -271,25 +271,31 @@ class LifecycleManager implements DisposableBean { > * @param bundle > */ > protected void maybeCloseApplicationContextFor(Bundle bundle) { >- final ConfigurableOsgiBundleApplicationContext context = >- (ConfigurableOsgiBundleApplicationContext) managedContexts.remove(Long.valueOf(bundle.getBundleId())); >+ final ConfigurableOsgiBundleApplicationContext context = managedContexts.remove(bundle.getBundleId()); > if (context == null) { > return; > } > >- RunnableTimedExecution.execute(new Runnable() { >+ Runnable shutdownTask = new Runnable() { > >- private final String toString = "Closing runnable for context " + context.getDisplayName(); >+ private final String toString = "Closing runnable for context " + context.getDisplayName(); > >- public void run() { >- closeApplicationContext(context); >- } >+ public void run() { >+ closeApplicationContext(context); >+ } > >- public String toString() { >- return toString; >- } >+ public String toString() { >+ return toString; >+ } >+ >+ }; >+ >+ if (extenderConfiguration.shouldShutdownAsynchronously()) { >+ RunnableTimedExecution.execute(shutdownTask, extenderConfiguration.getShutdownWaitTime(), shutdownTaskExecutor); >+ } else { >+ shutdownTask.run(); >+ } > >- }, extenderConfiguration.getShutdownWaitTime(), shutdownTaskExecutor); > } > > /** >diff --git a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfiguration.java b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfiguration.java >index 78560ce..765be66 100644 >--- a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfiguration.java >+++ b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfiguration.java >@@ -42,7 +42,12 @@ import org.springframework.util.ObjectUtils; > import java.io.UnsupportedEncodingException; > import java.net.URL; > import java.net.URLDecoder; >-import java.util.*; >+import java.util.ArrayList; >+import java.util.Collections; >+import java.util.Enumeration; >+import java.util.List; >+import java.util.Properties; >+import java.util.Timer; > > /** > * Configuration class for the extender. Takes care of locating the extender specific configurations and merging the >@@ -67,6 +72,8 @@ public class ExtenderConfiguration implements BundleActivator { > > private static final String PROPERTIES_NAME = "extenderProperties"; > >+ private static final String SHUTDOWN_ASYNCHRONOUS_KEY = "shutdown.asynchronously"; >+ > private static final String SHUTDOWN_WAIT_KEY = "shutdown.wait.time"; > > private static final String PROCESS_ANNOTATIONS_KEY = "process.annotations"; >@@ -91,7 +98,9 @@ public class ExtenderConfiguration implements BundleActivator { > // default dependency wait time (in milliseconds) > private static final long DEFAULT_DEP_WAIT = ConfigUtils.DIRECTIVE_TIMEOUT_DEFAULT * 1000; > private static final boolean DEFAULT_NS_BUNDLE_STATE = true; >- private static final long DEFAULT_SHUTDOWN_WAIT = 10 * 1000; >+ private static final boolean DEFAULT_SHUTDOWN_ASYNCHRONOUS = true; >+ private static final long DEFAULT_SHUTDOWN_WAIT = 10 * 1000; >+ > private static final boolean DEFAULT_PROCESS_ANNOTATION = false; > > private ConfigurableOsgiBundleApplicationContext extenderConfiguration; >@@ -106,6 +115,8 @@ public class ExtenderConfiguration implements BundleActivator { > > private long shutdownWaitTime, dependencyWaitTime; > >+ private boolean shutdownAsynchronously; >+ > private boolean processAnnotation, nsBundledResolved; > > private OsgiBundleApplicationContextEventMulticaster eventMulticaster; >@@ -128,7 +139,7 @@ public class ExtenderConfiguration implements BundleActivator { > // fields reading/writing lock > private final Object lock = new Object(); > >- /** >+ /** > * Constructs a new <code>ExtenderConfiguration</code> instance. Locates the extender configuration, creates an > * application context which will returned the extender items. > * >@@ -209,7 +220,8 @@ public class ExtenderConfiguration implements BundleActivator { > > synchronized (lock) { > shutdownWaitTime = getShutdownWaitTime(properties); >- dependencyWaitTime = getDependencyWaitTime(properties); >+ shutdownAsynchronously = getShutdownAsynchronously(properties); >+ dependencyWaitTime = getDependencyWaitTime(properties); > processAnnotation = getProcessAnnotations(properties); > } > >@@ -302,6 +314,7 @@ public class ExtenderConfiguration implements BundleActivator { > private Properties createDefaultProperties() { > Properties properties = new Properties(); > properties.setProperty(SHUTDOWN_WAIT_KEY, "" + DEFAULT_SHUTDOWN_WAIT); >+ properties.setProperty(SHUTDOWN_ASYNCHRONOUS_KEY, "" + DEFAULT_SHUTDOWN_ASYNCHRONOUS); > properties.setProperty(PROCESS_ANNOTATIONS_KEY, "" + DEFAULT_PROCESS_ANNOTATION); > properties.setProperty(WAIT_FOR_DEPS_TIMEOUT_KEY, "" + DEFAULT_DEP_WAIT); > >@@ -388,6 +401,10 @@ public class ExtenderConfiguration implements BundleActivator { > return Long.parseLong(properties.getProperty(SHUTDOWN_WAIT_KEY)); > } > >+ private boolean getShutdownAsynchronously(Properties properties) { >+ return Boolean.valueOf(properties.getProperty(SHUTDOWN_ASYNCHRONOUS_KEY)); >+ } >+ > private long getDependencyWaitTime(Properties properties) { > return Long.parseLong(properties.getProperty(WAIT_FOR_DEPS_TIMEOUT_KEY)); > } >@@ -452,6 +469,16 @@ public class ExtenderConfiguration implements BundleActivator { > } > } > >+ /** >+ * @return whether the application context shutdown during the bundle stop phase shall be >+ * performed asynchronously. >+ */ >+ public boolean shouldShutdownAsynchronously() { >+ synchronized (lock) { >+ return this.shutdownAsynchronously; >+ } >+ } >+ > /** > * Returns the dependencyWaitTime. > * >diff --git a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationCustomSettingsTest.java b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationCustomSettingsTest.java >index 8a58d2a..ece5843 100644 >--- a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationCustomSettingsTest.java >+++ b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationCustomSettingsTest.java >@@ -80,7 +80,11 @@ public class ExtenderConfigurationCustomSettingsTest extends TestCase { > assertEquals(300, config.getShutdownWaitTime()); > } > >- public void testShouldProcessAnnotation() throws Exception { >+ public void testShutdownAsynchronously() throws Exception { >+ assertFalse(config.shouldShutdownAsynchronously()); >+ } >+ >+ public void testShouldProcessAnnotation() throws Exception { > assertTrue(config.shouldProcessAnnotation()); > } > >diff --git a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationDefaultSettingsTest.java b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationDefaultSettingsTest.java >index 7f02cb5..736b04d 100644 >--- a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationDefaultSettingsTest.java >+++ b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationDefaultSettingsTest.java >@@ -66,7 +66,11 @@ public class ExtenderConfigurationDefaultSettingsTest extends TestCase { > assertEquals(10 * 1000, config.getShutdownWaitTime()); > } > >- public void testShouldProcessAnnotation() throws Exception { >+ public void testShutdownAsynchronously() throws Exception { >+ assertTrue(config.shouldShutdownAsynchronously()); >+ } >+ >+ public void testShouldProcessAnnotation() throws Exception { > assertFalse(config.shouldProcessAnnotation()); > } > >diff --git a/extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/support/extender-custom-config.xml b/extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/support/extender-custom-config.xml >index d6157b6..6b4dcb8 100644 >--- a/extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/support/extender-custom-config.xml >+++ b/extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/support/extender-custom-config.xml >@@ -24,6 +24,7 @@ > <prop key="smth">bla</prop> > <prop key="dependencies.wait.time">200</prop> > <prop key="shutdown.wait.time">300</prop> >+ <prop key="shutdown.asynchronously">false</prop> > <prop key="process.annotations">true</prop> > </util:properties> > </beans> >\ No newline at end of file >-- >1.8.0.msysgit.0 > > >From 1fb2ae248f3ed5cfc6843407753b4460db8ab096 Mon Sep 17 00:00:00 2001 >From: "olaf.otto" <olaf.otto@unic.com> >Date: Tue, 19 Mar 2013 14:59:57 +0100 >Subject: [PATCH 2/3] 403628: Asynchronous context shutdown causes timeouts > during > LifecycleManager#maybeCloseApplicationContextFor(Bundle) > in Apache Felix > (https://bugs.eclipse.org/bugs/show_bug.cgi?id=403628) > > - Added documentation > - Improved test coverage of the LifecycleManager >--- > docs/src/docbkx/reference/deployment.xml | 12 +- > .../internal/activator/LifecycleManager.java | 18 ++- > .../internal/activator/LifecycleManagerTest.java | 122 +++++++++++++++++++++ > 3 files changed, 146 insertions(+), 6 deletions(-) > create mode 100644 extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManagerTest.java > >diff --git a/docs/src/docbkx/reference/deployment.xml b/docs/src/docbkx/reference/deployment.xml >index 3177ef9..5b3263e 100644 >--- a/docs/src/docbkx/reference/deployment.xml >+++ b/docs/src/docbkx/reference/deployment.xml >@@ -469,7 +469,17 @@ Blueprint-Bundle: config/account-data-context.xml, config/osgi-*.xml > <entry>The amount of time the extender will wait for each application context to shutdown gracefully. Expressed in milliseconds.</entry> > <entry>10000 ms (10 s)</entry> > </row> >- >+ >+ <row> >+ <entry><literal>shutdown.asynchronously</literal></entry> >+ <entry><classname>boolean</classname></entry> >+ <entry> >+ Whether the extender shall shutdown each application context asynchronously. If <literal>false</literal>, >+ the <literal>shutdown.wait.time</literal> is ignored. Accordingly, application contexts blocking during close will block the bundle shutdown. >+ </entry> >+ <entry><literal>true</literal></entry> >+ </row> >+ > <row> > <entry><literal>dependencies.wait.time</literal></entry> > <entry><classname>java.lang.Long</classname></entry> >diff --git a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManager.java b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManager.java >index a43bcab..2b13cce 100644 >--- a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManager.java >+++ b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManager.java >@@ -276,9 +276,14 @@ class LifecycleManager implements DisposableBean { > return; > } > >+ maybeClose(context); >+ } >+ >+ protected void maybeClose(final ConfigurableOsgiBundleApplicationContext context) { >+ final String displayName = context.getDisplayName(); > Runnable shutdownTask = new Runnable() { > >- private final String toString = "Closing runnable for context " + context.getDisplayName(); >+ private final String toString = "Closing runnable for context " + displayName; > > public void run() { > closeApplicationContext(context); >@@ -293,12 +298,15 @@ class LifecycleManager implements DisposableBean { > if (extenderConfiguration.shouldShutdownAsynchronously()) { > RunnableTimedExecution.execute(shutdownTask, extenderConfiguration.getShutdownWaitTime(), shutdownTaskExecutor); > } else { >- shutdownTask.run(); >+ try { >+ shutdownTask.run(); >+ } catch (Exception e) { >+ log.error(displayName + " context shutdown failed.", e); >+ } > } >+ } > >- } >- >- /** >+ /** > * Closes an application context. This is a convenience methods that invokes the event notification as well. > * > * @param ctx >diff --git a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManagerTest.java b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManagerTest.java >new file mode 100644 >index 0000000..33b3839 >--- /dev/null >+++ b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManagerTest.java >@@ -0,0 +1,122 @@ >+package org.eclipse.gemini.blueprint.extender.internal.activator; >+ >+import junit.framework.TestCase; >+import org.easymock.MockControl; >+import org.eclipse.gemini.blueprint.context.ConfigurableOsgiBundleApplicationContext; >+import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration; >+ >+import static java.lang.Thread.yield; >+ >+/** >+ * @author Olaf Otto >+ */ >+public class LifecycleManagerTest extends TestCase { >+ private MockControl contextControl = MockControl.createControl(ConfigurableOsgiBundleApplicationContext.class); >+ private ConfigurableOsgiBundleApplicationContext context = (ConfigurableOsgiBundleApplicationContext) contextControl.getMock(); >+ >+ private MockControl osgiContextProcessorControl = MockControl.createControl(OsgiContextProcessor.class); >+ private OsgiContextProcessor osgiContextProcessor = (OsgiContextProcessor) osgiContextProcessorControl.getMock(); >+ >+ private boolean shouldShutdownAsynchronously; >+ >+ // Cannot mock a class with easymock 1.2 >+ ExtenderConfiguration configuration = new ExtenderConfiguration() { >+ @Override >+ public boolean shouldShutdownAsynchronously() { >+ return shouldShutdownAsynchronously; >+ } >+ >+ @Override >+ public long getShutdownWaitTime() { >+ return 0L; >+ } >+ }; >+ >+ private LifecycleManager testee = new LifecycleManager(this.configuration, null, null, null, this.osgiContextProcessor, null, null); >+ >+ public void testSuccessfulAsynchronousShutdown() throws Exception { >+ withAsynchronousShutdownDisabled(); >+ withSuccessfulContextClose(); >+ withPreAndPostProcessing(); >+ >+ shutdownContext(); >+ >+ verifyContextIsClosed(); >+ verifyOsgiContextProcessorInteractions(); >+ } >+ >+ public void testSuccessfulSynchronousShutdown() throws Exception { >+ withAsynchronousShutdownEnabled(); >+ withSuccessfulContextClose(); >+ withPreAndPostProcessing(); >+ >+ shutdownContext(); >+ >+ verifyContextIsClosed(); >+ verifyOsgiContextProcessorInteractions(); >+ } >+ >+ public void testFailingAsynchronousShutdown() throws Exception { >+ withAsynchronousShutdownEnabled(); >+ withFailingApplicationContextClose(); >+ withPreAndPostProcessing(); >+ >+ shutdownContext(); >+ yield(); >+ >+ verifyContextIsClosed(); >+ verifyOsgiContextProcessorInteractions(); >+ } >+ >+ public void testFailingSynchronousShutdown() { >+ withAsynchronousShutdownDisabled(); >+ withFailingApplicationContextClose(); >+ withPreAndPostProcessing(); >+ >+ shutdownContext(); >+ >+ verifyContextIsClosed(); >+ verifyOsgiContextProcessorInteractions(); >+ } >+ >+ private void withFailingApplicationContextClose() { >+ this.context.getDisplayName(); >+ this.contextControl.setReturnValue("Display name"); >+ this.context.close(); >+ this.contextControl.setThrowable(new RuntimeException("THIS IS AN EXPECTED TEST EXCEPTION")); >+ } >+ >+ private void verifyContextIsClosed() { >+ this.contextControl.verify(); >+ } >+ >+ private void verifyOsgiContextProcessorInteractions() { >+ this.osgiContextProcessorControl.verify(); >+ } >+ >+ private void withPreAndPostProcessing() { >+ this.osgiContextProcessor.preProcessClose(this.context); >+ this.osgiContextProcessor.postProcessClose(this.context); >+ } >+ >+ private void withSuccessfulContextClose() { >+ this.context.close(); >+ this.context.getDisplayName(); >+ this.contextControl.setDefaultReturnValue("Nothing"); >+ } >+ >+ private void shutdownContext() { >+ this.contextControl.replay(); >+ this.osgiContextProcessorControl.replay(); >+ >+ this.testee.maybeClose(this.context); >+ } >+ >+ private void withAsynchronousShutdownDisabled() { >+ this.shouldShutdownAsynchronously = false; >+ } >+ >+ private void withAsynchronousShutdownEnabled() { >+ this.shouldShutdownAsynchronously = true; >+ } >+} >-- >1.8.0.msysgit.0 > > >From d0ea0453a8e0e445d26939b7f40ce59246ba8718 Mon Sep 17 00:00:00 2001 >From: "olaf.otto" <olaf.otto@unic.com> >Date: Tue, 19 Mar 2013 16:06:52 +0100 >Subject: [PATCH 3/3] 403628: Asynchronous context shutdown causes timeouts > during > LifecycleManager#maybeCloseApplicationContextFor(Bundle) > in Apache Felix > (https://bugs.eclipse.org/bugs/show_bug.cgi?id=403628) > > - Added missing license headers >--- > .../extender/internal/activator/LifecycleManagerTest.java | 14 ++++++++++++++ > 1 file changed, 14 insertions(+) > >diff --git a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManagerTest.java b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManagerTest.java >index 33b3839..9bbcfb1 100644 >--- a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManagerTest.java >+++ b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManagerTest.java >@@ -1,3 +1,17 @@ >+/****************************************************************************** >+ * Copyright (c) 2006, 2010 VMware Inc., Oracle Inc. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * and Apache License v2.0 which accompanies this distribution. >+ * The Eclipse Public License is available at >+ * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0 >+ * is available at http://www.opensource.org/licenses/apache2.0.php. >+ * You may elect to redistribute this code under either of these licenses. >+ * >+ * Contributors: >+ * VMware Inc. >+ * Oracle Inc. >+ *****************************************************************************/ > package org.eclipse.gemini.blueprint.extender.internal.activator; > > import junit.framework.TestCase; >-- >1.8.0.msysgit.0 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 403628
:
228584
| 228646