On 07/30/2013 09:01 PM, Domi wrote:
In your example, how @AddaptField know to which type he should adapt the field? 
e.g. Why to List instead and not Collection?

The current type of the field is what it adapts to.

        @AdaptField
        protected volatile DescribableList<...> triggers = ...

The annotation is a sign that whoever refers to this 'triggers' field, regardless of what that byte code says as the type, gets adapted to the current type DescribableList.


Am 31.07.2013 um 01:38 schrieb Kohsuke Kawaguchi <[email protected]>:


I wrote a small bytecode transformation engine so that we can further evolve 
code while maintaining the backward compatibility:

https://github.com/jenkinsci/bytecode-compatibility-transformer


This is a pair of an annotation and a bytecode transformer.

For example, I recently (somewhat inadvertently) changed 
AbstractProject.triggers from List to DescribableList, and this is causing 
various linkage errors when loading plugins. But with this library, I can add:

   @AdaptField
   protected volatile DescribableList<...> triggers = ...

... and the bytecode transformer can rewrite a reference to this field so that 
things will work (unless you try to set something like ArrayList to this field, 
which would fail with ClassCastException.)

Since Jenkins controls classloading of all plugins, installing such a 
transformer can be done in a core without changing plugins.


Another use for this is to get rid of a singleton, for example like in the 
FreeStyleProject class:

   @Restricted(NoExternalUse.class)
   @Extension(ordinal=1000)
   public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();

   public static final class DescriptorImpl extends AbstractProjectDescriptor {
      ....
   }

I could change this to:

   @Extension(ordinal=1000)
   public static final class DescriptorImpl extends AbstractProjectDescriptor {
      ....
   }

   @AdaptField("DESCRIPTOR")
   @Restricted(NoExternalUse.class)
   public static DescriptorImpl _getDescriptor() {
      return ...;
   }


For these benefits, I'd like to integrate this into the main line unless I hear 
some objections.

So far we've relied on bridge method injector [1] to do some code evolutions, 
and I think this will be another valuable tool to push that even further. And 
yes, this is not a tool for an inexperienced. Plugins would be able to use the 
same mechanism, but use this at your own risk.


I haven't thought about how to integrate this into remoting, but we control 
classloading there as well, so it should be doable.

Besides, this is useful enough just on the master, and there are many objects 
in the master that really can't be sent to slaves, like Jenkins, Job, and Run.



[1] http://bridge-method-injector.infradna.com/
--
Kohsuke Kawaguchi | CloudBees, Inc. | http://cloudbees.com/
Try Jenkins Enterprise, our professional version of Jenkins

--
You received this message because you are subscribed to the Google Groups "Jenkins 
Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.





--
Kohsuke Kawaguchi | CloudBees, Inc. | http://cloudbees.com/
Try Jenkins Enterprise, our professional version of Jenkins

--
You received this message because you are subscribed to the Google Groups "Jenkins 
Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to