Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-19508

Replace @Extension(optional=true) and optional dependencies with bridge plugins

    Details

    • Similar Issues:

      Description

      Optional dependencies are extremely fragile.

      You must take care to mark each @Extension pertaining to the dependency with optional=true. But this only actually works if a NoClassDefFoundError would be thrown when trying to load the extension with the dependency missing. Sometimes this happens reliably, for example if the extension point is defined in that dependency, but in other cases it only happens incidentally via something like a static initializer. That means that a seemingly minor refactoring can cause the extension to suddenly start getting loaded even when the dependency is missing, causing serious linkage errors later on. http://release-notes.cloudbees.com/release/Folders/3.11 is an example. Even in the best of cases, a missing dependency leads to a warning in the log file which can be alarming to a user.

      Another problem with optional dependencies is testing: JenkinsRule-based functional tests have the dependency enabled, so you are never testing the lack of the dependency. If the code does dynamic checks for the existence of the dependency using Jenkins.getInstance().getPlugin("shortName"), one code branch is not fully covered.

      There is also an inherent asymmetry. If plugins A and B need to interact, should A have an optional dependency on B, or should B have an optional dependency on A? The decision is often political, i.e. if A is more widely used or "fundamental" then probably B will be given the dependency on A. But in many cases the direction is not at all clear, e.g. interactions with Job Config History, Parameterized Trigger, etc. Sometimes the dependency is simply added to the more actively maintained plugin. The problem gets murkier when one of the plugins becomes deprecated, as in https://github.com/jenkinsci/join-plugin/pull/6—should the dependency be removed to "clean house", even though this would remove functionality for the handful of users still running the deprecated plugin?

      Since creating and publishing plugins is pretty cheap, it would make more sense to me to factor out such an integration between two plugins into a third "bridge" plugin with hard dependencies on each (and an extension point implementation providing the integration). This avoids the need for any conditional branches, optional=true, or asymmetry. The only thing missing is a way for users to be guided to install the bridge plugin. Perhaps one or both of the main plugins could include a manifest header saying that they "recommend" the bridge (in case the other main plugin is also enabled). The update center UI would automatically schedule the installation of the bridge if the user requested both of the main plugins to be installed (or already had one installed and requested the other). Compare "eager" modules in NetBeans: http://bits.netbeans.org/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/api.html#enablement

        Attachments

          Issue Links

            Activity

            Hide
            scm_issue_link SCM/JIRA link daemon added a comment -

            Code changed in jenkins
            User: Jesse Glick
            Path:
            src/main/java/com/cloudbees/hudson/plugins/folder/properties/FolderCredentialsProvider.java
            http://jenkins-ci.org/commit/cloudbees-folder-plugin/acf46b49786d501416b1bb1b306e5692bdc3ea45
            Log:
            Yet another JENKINS-19508 workaround.

            Show
            scm_issue_link SCM/JIRA link daemon added a comment - Code changed in jenkins User: Jesse Glick Path: src/main/java/com/cloudbees/hudson/plugins/folder/properties/FolderCredentialsProvider.java http://jenkins-ci.org/commit/cloudbees-folder-plugin/acf46b49786d501416b1bb1b306e5692bdc3ea45 Log: Yet another JENKINS-19508 workaround.
            Hide
            jglick Jesse Glick added a comment -

            Another problem is that an optional extension which is initially broken due to a missing optional dependency does not get added when that dependency is installed—you have to restart Jenkins.

            Show
            jglick Jesse Glick added a comment - Another problem is that an optional extension which is initially broken due to a missing optional dependency does not get added when that dependency is installed—you have to restart Jenkins.
            Hide
            scm_issue_link SCM/JIRA link daemon added a comment -

            Code changed in jenkins
            User: Cyrille Le Clerc
            Path:
            jenkins-plugin/pom.xml
            jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/listeners/DownstreamPipelineTriggerRunListener.java
            http://jenkins-ci.org/commit/pipeline-maven-plugin/f12c104daa1464b8e759a50b1c2e5aaa441e1516
            Log:
            Merge pull request #83 from jglick/deps

            JENKINS-19508 Eliminate some optional deps

            Compare: https://github.com/jenkinsci/pipeline-maven-plugin/compare/895db724818f...f12c104daa14

            Show
            scm_issue_link SCM/JIRA link daemon added a comment - Code changed in jenkins User: Cyrille Le Clerc Path: jenkins-plugin/pom.xml jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/listeners/DownstreamPipelineTriggerRunListener.java http://jenkins-ci.org/commit/pipeline-maven-plugin/f12c104daa1464b8e759a50b1c2e5aaa441e1516 Log: Merge pull request #83 from jglick/deps JENKINS-19508 Eliminate some optional deps Compare: https://github.com/jenkinsci/pipeline-maven-plugin/compare/895db724818f...f12c104daa14

              People

              • Assignee:
                Unassigned
                Reporter:
                jglick Jesse Glick
              • Votes:
                2 Vote for this issue
                Watchers:
                8 Start watching this issue

                Dates

                • Created:
                  Updated: