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:

      @Target({TYPE}) // TBD: on Descriptor, or its clazz?
      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);


      • 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.

            jglick Jesse Glick
            jglick Jesse Glick
            0 Vote for this issue
            3 Start watching this issue