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

Ability to override reflective metadata in DescribableModel

    • Icon: New Feature New Feature
    • Resolution: Fixed
    • Icon: Major Major
    • structs-plugin
    • structs 1.18

      Following up an old semi-suggestion on the dev list with daspilker and in discussion with stephenconnolly, I propose a new API in symbol-annotation (so that it could be used from core, not just plugins) that would allow a Describable author to completely customize how instantiate and uninstantiate work, if the POJO-style reflective metadata is not quite right. DescribableModel would then delegate to the custom implementation, which would in turn be able to partly delegate back to the standard implementations where desired.

      Rough  API sketch:

      @Retention(RUNTIME)
      @Target({TYPE}) // TBD: on Descriptor, or its clazz?
      @Documented
      public @interface CustomDescription {
          Class<CustomDescribableModel> value();
      }
      public interface CustomDescribableModel<T> {
          Class<T> getType();
          T instantiate(Map<String, Object> arguments, StandardInstantiator standard);
          Map<String, Object> uninstantiate(T object, StandardUninstantiator standard);
      }
      public interface StandardInstantiator {
          <T> T instantiate(Class<T> type, Map<String, Object> arguments);
      }
      public interface StandardUninstantiator {
          Map<String, Object> uninstantiate(Object object);
      }
      

      TBD:

      • How to deal with UninstantiatedDescribable, defined in the plugin not the annotation library, and which is necessary to support symbols?
      • Is it necessary to be able to override other behaviors of DescribableModel that are currently hard-coded to use reflection, such as the soleRequiredParameter?
      • Can a CustomDescribableModel implementation really be used from, say, job-dsl, given that the implementation would reside in a plugin and might link to any classes in Jenkins? Currently job-dsl runs in-process in the master JVM, but other similar tools run out of process. This is the downside of a procedural override as opposed to annotations.

      Use cases:

      • GerritTrigger could call the standard implementations but rename map entries with keys like gerritBuildFailedCodeReviewValue to something more concise.
      • ChoiceParameterDefinition could correct the type of choices from the PoV of scripts.
      • SCMSourceRetriever in workflow-cps-global-lib could delete .scm.id from uninstantiation results, so that Pipeline Syntax would not offer a random UUID for this form of the library step. (In this use case the SCMSource is never given an owner or otherwise persisted, so its id is irrelevant.) Note that StandardUninstantiator may be called on any object, not necessarily the root object passed into CustomDescribableModel.
      • When refactoring describables into new structures, existing fields, getters, and setters could be retained at the Java level, while providing only the new, recommended form to Pipeline Syntax and similar tools.

          [JENKINS-44892] Ability to override reflective metadata in DescribableModel

          Jesse Glick added a comment -

          JENKINS-44864 is an example of a use case which a custom override could also solve more generally, though it is a reasonable enough change to the default implementation.

          Jesse Glick added a comment - JENKINS-44864  is an example of a use case which a custom override could also solve more generally, though it is a reasonable enough change to the default implementation.

          Jesse Glick added a comment -

          Could be helpful for JENKINS-37227, for example providing a simplified GitSCM.url as an alternative to a singleton list of UserRemoteConfig. We would want to retain the existing general field for compatibility, without deprecating it, but still prefer to offer just url from uninstantiate.

          Jesse Glick added a comment - Could be helpful for  JENKINS-37227 , for example providing a simplified GitSCM.url as an alternative to a singleton list of UserRemoteConfig . We would want to retain the existing general field for compatibility, without deprecating it, but still prefer to offer just url from uninstantiate .

          jglick I assume this will be transparent for job-dsl and DescribableModel would take care of detecting a CustomDescription thus hiding the details for the caller. In this case it should work for job-dsl. Please ping me if you have a PR to test. The job-dsl build step runs in the master JVM, but there are other usages of the DSL which do not run in the master JVM. But those are limited to the static built-in DSL. The dynamic DescribableModel stuff is only available when running in the master JVM.

          Daniel Spilker added a comment - jglick I assume this will be transparent for job-dsl and DescribableModel would take care of detecting a CustomDescription thus hiding the details for the caller. In this case it should work for job-dsl . Please ping me if you have a PR to test. The job-dsl build step runs in the master JVM, but there are other usages of the DSL which do not run in the master JVM. But those are limited to the static built-in DSL. The dynamic DescribableModel stuff is only available when running in the master JVM.

          Jesse Glick added a comment -

          I do not have any PRs to test; needs a concrete design first.

          Jesse Glick added a comment - I do not have any PRs to test; needs a concrete design first.

          Jesse Glick added a comment -

          structs PR 18 proposes a new or overloaded annotation just to handle the common case of parameter aliasing. Would require these calls to look up an annotation on a method, field, or constructor parameter, as well as some other changes to handle instantiation with aliased constructor parameters.

          For StepDescriptor it is not critical since you can already override newInstance and uninstantiate, which handles both build runtimes and the dynamic snippet generator, though the static reference documentation knows nothing of your override and will not reflect the alias.

          Jesse Glick added a comment - structs PR 18 proposes a new or overloaded annotation just to handle the common case of parameter aliasing. Would require these calls to look up an annotation on a method, field, or constructor parameter, as well as some other changes to handle instantiation with aliased constructor parameters. For StepDescriptor it is not critical since you can already override newInstance and uninstantiate , which handles both build runtimes and the dynamic snippet generator, though the static reference documentation knows nothing of your override and will not reflect the alias.

          Jesse Glick added a comment -

          Besides Pipeline and Job DSL, the other major potential consumer of this sort of API would be the configuration-as-code plugin, for YAML-based global configuration. Unfortunately it does not use structs / DescribableModel for whatever reason, so it would not be able to honor these customizations unless that were changed. CC ewel ndeloof

          Jesse Glick added a comment - Besides Pipeline and Job DSL, the other major potential consumer of this sort of API would be the configuration-as-code plugin, for YAML-based global configuration. Unfortunately it does not use structs / DescribableModel for whatever reason, so it would not be able to honor these customizations unless that were changed. CC ewel ndeloof

          Jesse Glick added a comment -

          JEP-205 is another proposal to define a new standard for databinding. It is strictly declarative, which has some obvious advantages—certainly kinds of tools can be written which rely on it, and introspection can happen outside the Jenkins JVM—but which also renders it impractical for solving particular customizations such as for JENKINS-51638.

          Jesse Glick added a comment - JEP-205 is another proposal to define a new standard for databinding. It is strictly declarative, which has some obvious advantages—certainly kinds of tools can be written which rely on it, and introspection can happen outside the Jenkins JVM—but which also renders it impractical for solving particular customizations such as for JENKINS-51638 .

          Jesse Glick added a comment -

          daspilker I have proposed an API and would like feedback on whether you think it makes sense for Job DSL.

          Jesse Glick added a comment - daspilker I have proposed an API and would like feedback on whether you think it makes sense for Job DSL.

          Devin Nusbaum added a comment -

          The new CustomDescribableModel API was just released in version 1.18 of Structs.

          Devin Nusbaum added a comment - The new CustomDescribableModel API was just released in version 1.18 of Structs.

            jglick Jesse Glick
            jglick Jesse Glick
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: