Hi John, Thanks for the suggestions. I like “@RegisterableFunction” better than “@RegisterFunction". I think that we don’t want @RegisterableFunction to be @Inherited, in order to avoid creating a new variant of the problem we are trying to fix. As you suggest, we should be mindful to document the behavior clearly.
In case you’re interested, here’s <https://github.com/lukehutch/fast-classpath-scanner/wiki/3.4.-Finding-classes-with-specific-annotations-or-meta-annotations> some documentation of the API for the library we’re using for the annotation scanning. It scans the binary byte code files directly, rather than using a Class reference like Spring utilities you pointed out (which AFAIK requires having that class loaded in the JVM). Thanks, Jared > On Aug 11, 2017, at 11:00 AM, John Blum <jb...@pivotal.io> wrote: > > Hi Jared- > > In general, I like this idea since Annotations are a great form of > meta-data and essentially meaningless outside of the intended context and > therefore do not impose any adverse effects on any existing behavior. > > However, 2 things... 1 suggestion and 1 caution... > > > 1. Perhaps "RegisterableFunction" as opposed to "RegisterFunction". > > > 2. Annotations can be "inherited" in the same way that your ConcreteFunction > extends (inherits from) AbstractFunction, so too can a more concrete > Function possibly inherit from a less-concrete-but-not-abstract Function. > A developer might expect that they don't have to re-annotated his/her > function. > > For example... > > @RegisterableFunction > class ProcessOrder extends FunctionAdapter { ... } > > class CreateAccountAtPointOfSale extends ProcessOrder { ... } > > If these are in separate JAR files, depending on the "application", I may > only want to "register" the CreateAccountAtPointOfSale Function and not the > ProcessOrder Function explicitly. Please forgive my example here since it > seems like a bad example given it feels like 2 separate actions but is > often part of the same workflow and so really depends on how application > developers think about and organize their logic, which usually leads to > "unexpected" things you never anticipated when introducing something like > this. > > SIDE NOTE: Of course, from a Java SE standpoint, the "RegisteredFunction" > Annotation could be (but does not have to be) meta-annotated with @Inherited., > such as... > > @Target(ElementType.TYPE) > @Retention(RetentionPolicy.RUNTIME) > @Inherited > ... > @interface RegisteredFunction { .. } > > > *Spring* takes all of these things into account when it processes > annotations of this nature (e.g. @Enable...). Especially have a look at > o.s.core.annotation.AnnotatedElementUtils [1] and even > o.s.core.annotation.AnnotationUtils [2]. These are very robust and very > powerful classes underpinning much of *Spring's* Annotation configuration > and processing. *Boot* also extends this functionality and *Spring* > Annotation config in very specific/custom ways. > > I think it is reasonable to set limitations to keep the initial scope > small, but be sure those are well documented since users will be coming > from many different frameworks having many different expectations. > > Food for thought/hope this helps. > > Regards, > -John > > > [1] > http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/annotation/AnnotatedElementUtils.html > [2] > http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/annotation/AnnotationUtils.html > > > > > > On Fri, Aug 11, 2017 at 10:22 AM, Jared Stewart <jstew...@pivotal.io> wrote: > >> Recent changes introduced to avoid the eager loading of classes have lead >> to Functions not getting registered correctly if the class hierarchy >> leading up to Function (or FunctionAdapter) is split up across multiple jar >> files. We propose to introduce a new annotation to identify functions in >> such a case. >> Consider the following scenario: >>> Abstract.jar - public abstract class AbstractFunction implements >> Function {...} >>> Concrete.jar - public class ConcreteFunction extends AbstractFunction >> {...} >> When Concrete.jar is deployed, we only scan the classes inside >> Concrete.jar. This means that we have no way of knowing that >> AbstractFunction eventually leads up to Function. (We could load >> ConcreteFunction to see if it implements Function via reflection or >> Function.class.isAssignableFrom(), but then we would be back to eagerly >> loading all of the classes to see whether or not they implement Function.) >> We propose a new annotation (perhaps @RegisterFunction, suggestions are >> welcome) to designate a class as a Function in such a case. Since we are >> able to scan classes for annotations without loading them, this will allow >> us to identify ConcreteFunction as a Function without eagerly loading all >> of the classes in Concrete.jar. >> I should emphasize that ConcreteFunction already is registered as expected >> if it resides in the same jar file as AbstractFunction. This annotation >> would only be relevant when the class hierarchy leading up to Function is >> spread across multiple jar files. >> - Jared > > > > > -- > -John > john.blum10101 (skype)