diff --git a/changelog.html b/changelog.html
index 721f5e71e5..154d84209c 100644
--- a/changelog.html
+++ b/changelog.html
@@ -63,6 +63,9 @@ Upcoming changes
(issue 22262)
identity.key, used to secure some communications with Jenkins, now stored encrypted with the master key.
+
+ When dynamically loading a plugin which another loaded plugin already had an optional dependency on, class loading errors could result before restart.
+ (issue 19976)
Memory leaks in the old data monitor.
(issue 19544)
diff --git a/core/src/main/java/hudson/ClassicPluginStrategy.java b/core/src/main/java/hudson/ClassicPluginStrategy.java
index 18cbb3e0fa..f321605afe 100644
--- a/core/src/main/java/hudson/ClassicPluginStrategy.java
+++ b/core/src/main/java/hudson/ClassicPluginStrategy.java
@@ -377,15 +377,6 @@ public class ClassicPluginStrategy implements PluginStrategy {
plugin.getPlugin().start();
}
- /**
- * Called when a plugin is deployed, and there is a plugin optionally depending on that plugin.
- * The class loader of the existing depending plugin should be updated
- * to load classes from the newly deployed plugin.
- *
- * @param depender the plugin to update its class loader
- * @param dependee
- * @see hudson.PluginStrategy#updateDependency(hudson.PluginWrapper, hudson.PluginWrapper)
- */
@Override
public void updateDependency(PluginWrapper depender, PluginWrapper dependee) {
DependencyClassLoader classLoader = findAncestorDependencyClassLoader(depender.classLoader);
diff --git a/core/src/main/java/hudson/PluginManager.java b/core/src/main/java/hudson/PluginManager.java
index d77f12087d..17900b6309 100644
--- a/core/src/main/java/hudson/PluginManager.java
+++ b/core/src/main/java/hudson/PluginManager.java
@@ -464,7 +464,11 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas
if (d.shortName.equals(p.getShortName())) {
// this plugin depends on the newly loaded one!
// recalculate dependencies!
- getPluginStrategy().updateDependency(depender, p);
+ try {
+ getPluginStrategy().updateDependency(depender, p);
+ } catch (AbstractMethodError x) {
+ LOGGER.log(WARNING, "{0} does not yet implement updateDependency", getPluginStrategy().getClass());
+ }
break;
}
}
diff --git a/core/src/main/java/hudson/PluginStrategy.java b/core/src/main/java/hudson/PluginStrategy.java
index d61e23732a..e599812e4a 100644
--- a/core/src/main/java/hudson/PluginStrategy.java
+++ b/core/src/main/java/hudson/PluginStrategy.java
@@ -79,10 +79,12 @@ public interface PluginStrategy extends ExtensionPoint {
List> findComponents(Class type, Hudson hudson);
/**
- * Called when a plugin that is depended by another plugin is newly deployed.
- *
+ * Called when a plugin is installed, but there was already a plugin installed which optionally depended on that plugin.
+ * The class loader of the existing depending plugin should be updated
+ * to load classes from the newly installed plugin.
* @param depender plugin depending on dependee.
* @param dependee newly loaded plugin.
+ * @since 1.557
*/
void updateDependency(PluginWrapper depender, PluginWrapper dependee);
}
diff --git a/test/src/test/java/hudson/PluginManagerTest.java b/test/src/test/java/hudson/PluginManagerTest.java
index b068598c94..4f50aec47f 100644
--- a/test/src/test/java/hudson/PluginManagerTest.java
+++ b/test/src/test/java/hudson/PluginManagerTest.java
@@ -33,13 +33,6 @@ import hudson.model.UpdateSite;
import hudson.scm.SubversionSCM;
import hudson.util.FormValidation;
import hudson.util.PersistedList;
-import org.apache.commons.io.FileUtils;
-import org.apache.tools.ant.filters.StringInputStream;
-import org.jvnet.hudson.test.HudsonTestCase;
-import org.jvnet.hudson.test.Url;
-import org.jvnet.hudson.test.recipes.WithPlugin;
-import org.jvnet.hudson.test.recipes.WithPluginManager;
-
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
@@ -47,6 +40,13 @@ import java.net.URLClassLoader;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Future;
+import org.apache.commons.io.FileUtils;
+import org.apache.tools.ant.filters.StringInputStream;
+import org.jvnet.hudson.test.Bug;
+import org.jvnet.hudson.test.HudsonTestCase;
+import org.jvnet.hudson.test.Url;
+import org.jvnet.hudson.test.recipes.WithPlugin;
+import org.jvnet.hudson.test.recipes.WithPluginManager;
/**
* @author Kohsuke Kawaguchi
@@ -310,6 +310,7 @@ public class PluginManagerTest extends HudsonTestCase {
*
* @throws Exception
*/
+ @Bug(19976)
public void testInstallDependedPluginWithoutRestart() throws Exception {
// Load depender.
{