I see what you did with the annotation processor. I figured I’d be able to
add more metadata in the service class generated basically. If we can
identify the various logical scopes in the library, I think that could lead
to less potential bugs.

On Sun, Nov 3, 2019 at 14:14 Ralph Goers <ralph.go...@dslextreme.com> wrote:

> I have a couple of comments:
> It isn’t really possible for me to know what you are suggesting without
> seeing some examples of how plugins would be defined.
> I have a suspicion the scopes could get nasty. Some plugins would be tied
> to the LoggerContext, which essentially has a lifetime of the ClassLoader
> (or Bundle, or Module), while others are tied to the configuration so have
> that lifetime. I am afraid of the problems that would be introduced if a
> Plugin tied to the LoggerContext suddenly has a configuration scope. That
> would mean having to worry about thread safety in places we currently may
> not have to.  But again, I would want to see examples to be sure.
> Using the annotation processor in 3.0 is currently required when using
> OSGi or JPMS. This is because OSGi requires bundle loading and JPMS
> requires the use of the ServiceLoader. We do not want to have to load each
> and every plugin via the ServiceLoader so instead the PluginService  class
> is loaded, which contains a Map of all the plugins in the bundle/module.  I
> don’t see how you can avoid this.  That said, you are certainly free to
> make the PluginService smarter and more efficient.
>
> Ralph
>
> > On Nov 3, 2019, at 12:18 PM, Matt Sicker <boa...@gmail.com> wrote:
> >
> > Oh, almost forgot to mention my other main goal here: I have a
> > hypothesis that if designed our APIs with inversion of control in
> > mind, programmatic configuration and extension should be _much_ easier
> > to support while maintaining backward compatibility, too. While the
> > configuration framework itself is extremely powerful for creating
> > fairly dynamic configurations, a non-trivial amount of users want more
> > programmatic control than any of the APIs we support.
> >
> > On Sat, 2 Nov 2019 at 16:04, Matt Sicker <boa...@gmail.com> wrote:
> >>
> >> I've been working on this part time over the weekends lately, and
> >> after exploring a bit of Guice and CDI, I've come to the conclusion
> >> that if we were to rebase the plugin system on any annotation style,
> >> it seems as though CDI provides a fairly good set of extensions to
> >> javax.inject which would potentially work well with our existing
> >> annotations for backward compatibility. I wouldn't want to introduce
> >> an actual dependency on it, but a plugin SPI inspired by it could
> >> potentially work. A nice advantage to adopting a CDI-like system is
> >> that it should be simpler to use by other developers who aren't
> >> familiar with our custom framework.
> >>
> >> General overview of potential changes:
> >>
> >> * In addition to scopes and qualifiers, introduce stereotype
> >> annotations which are used for combining multiple annotations. This
> >> will help a lot in making old annotations still work properly.
> >> * Introduce a Produces and Disposes annotation that work similarly to
> CDI.
> >> * Introduce a PostConstruct and PreDestroy annotation because later
> >> versions of Java removed them from the base JDK (they're in a separate
> >> module from java.base), and javax.inject is supposed to support those
> >> annotations.
> >> * Introduce a "Configuration" scope which lives for the life of a
> >> configuration. This would essentially replace the concept of a "core"
> >> plugin category as they map to the lifecycle of a configuration
> >> source.
> >> * Use the "Singleton" scope for anything we'd want to live for the
> >> entire application instance (generally replaces use of system property
> >> singletons where possible).
> >> * Integrate some common scopes like request-scoped, session-scoped,
> >> etc., to allow for a more pluggable system for introducing scopes for
> >> Lookups or other plugins.
> >> * Use the PostConstruct/PreDestroy callbacks to replace initialize and
> >> destroy methods in plugins. This might work well toward generic
> >> lifecycle management which is currently done ad hoc.
> >> * I have a vague notion that a "LogEvent" scope would be really neat,
> >> but such a system would likely not work well with GC-free code, so I'm
> >> not really considering this one at the moment.
> >> * PluginAttribute/PluginBuilderAttribute/PluginElement/PluginValue all
> >> become stereotype qualifiers with some annotation compatibility checks
> >> to support old annotations.
> >> * PluginFactory becomes a stereotype producer annotation.
> >> * PluginBuilderFactory (previously deleted) would also be a stereotype
> >> producer annotation.
> >>
> >> One thing I'm experimenting with right now that should really help
> >> inform me whether or not this effort will be worth it is breaking this
> >> down into an SPI that will have two default implementations: one based
> >> on runtime reflection, and another based on generated code from the
> >> annotation processor (a more advanced version of the existing
> >> PluginService code generator). I hope to avoid the use of actual
> >> reflection APIs in the generated code to more easily support GraalVM
> >> as well as to hopefully offload a bit of the reflective initialization
> >> to compile-time rather than at runtime (fairly useful for
> >> microservices where startup time is more important).
> >>
> >> I do have an overarching purpose behind all this: I'd like to
> >> dramatically reduce the tight coupling between Configuration, Node,
> >> and plugin classes. Some of this is in the form of a more generic
> >> dependency injection API to avoid the need for manually calling
> >> Configuration methods in plugin factories. Another is to make various
> >> services provided by Configuration to instead be injected directly as
> >> parameters to the plugin factories. Reducing the coupling between
> >> plugins and other running parts of the system should help reduce the
> >> complexity of many tests as well, and it may also help reduce the time
> >> taken running tests, though that will still likely be affected by the
> >> various integration tests regardless.
> >>
> >> On Wed, 9 Oct 2019 at 16:52, Matt Sicker <boa...@gmail.com> wrote:
> >>>
> >>> Part of this is to make it simpler to access globally configured
> >>> things without having to pass around a Configuration everywhere. If
> >>> plugins can declare the explicit parts of the API they need access to
> >>> rather than the full Configuration, that should make tests a bit
> >>> lighter and easier to write.
> >>>
> >>> On Wed, 9 Oct 2019 at 16:11, Ralph Goers <ralph.go...@dslextreme.com>
> wrote:
> >>>>
> >>>> FWIW, I don’t think @Inject is a good replacement for
> @PluginFactory.  @Inject is essentially the same as @Autowired.  It should
> be placed on fields where you want the implementation to be injected.
> @Inject specified on a method implies that the method parameters should be
> injected. I don’t think that is what you are intending.
> >>>>
> >>>> Ralph
> >>>>
> >>>>> On Oct 9, 2019, at 1:38 PM, Ralph Goers <ralph.go...@dslextreme.com>
> wrote:
> >>>>>
> >>>>> Ok, but given @Scope and @Qualifier can only be used to annotate the
> existing PluginElement, PluginAttribute and PluginValue annotations I am
> not sure what they buy you. They can’t be used to replace the existing
> annotations as they are only allowed to be used on annotation
> declarations.  I agree that @PluginConfiguration is somewhat redundant. All
> we are really doing with it is saying that the existing Configuration
> object should be passed to the method. Using @PluginConfiguration for that
> is easy but using @Inject as an indicator and checking the type of the
> parameter could just as easily be done.
> >>>>>
> >>>>> I guess I would like to see what you think an example plugin would
> look like before going further.
> >>>>>
> >>>>> Ralph
> >>>>>
> >>>>>
> >>>>>
> >>>>>> On Oct 9, 2019, at 11:46 AM, Matt Sicker <boa...@gmail.com> wrote:
> >>>>>>
> >>>>>> I want to make it simpler to write plugins. Increase testability,
> reuse
> >>>>>> more standard APIs that others would be more familiar with (easier
> >>>>>> onboarding), and make it simpler to implement some tangentially
> related
> >>>>>> feature ideas.
> >>>>>>
> >>>>>> As for the builder versus factory annotation, there was already
> special
> >>>>>> support for collections and maps that weren’t explicit annotations,
> so
> >>>>>> determining what to do based on the return type of the factory
> method was
> >>>>>> already an established idea. I think it made sense to combine them
> all into
> >>>>>> @PluginFactory, and because of that, I noticed the correspondence
> between
> >>>>>> that and @Inject.
> >>>>>>
> >>>>>> On Wed, Oct 9, 2019 at 13:28, Ralph Goers <
> ralph.go...@dslextreme.com>
> >>>>>> wrote:
> >>>>>>
> >>>>>>> I still don’t understand what the benefit is. IIUC your plan is to
> add the
> >>>>>>> @Scope and @Qualifier annotations to the @PluginElement and
> >>>>>>> @PluginAttribute.  If that somehow helps, great, as it is will be
> invisible
> >>>>>>> to plugin developers.
> >>>>>>>
> >>>>>>> One thing I find odd is that Builders were annotated with
> >>>>>>> @PluginBuilderFactory and are now annotated with @PluginFactory.
> >>>>>>> Previously, only factory methods were annotated with
> @PluginFactory.  What
> >>>>>>> is odd is that the methods previously annotated with
> @PluginBuilderFactory
> >>>>>>> create a Builder. They builder then creates the plugin object.
> However the
> >>>>>>> methods annotated with @PluginFactory directly created the plugin
> object.
> >>>>>>> Now you have both annotated with @PluginFactory, which means some
> methods
> >>>>>>> behave one way and others behave another way. How is that clearer?
> >>>>>>>
> >>>>>>> That said changing both to @Inject has some merit although I am
> not sure
> >>>>>>> how you are determining that one is creating a Builder that then
> creates
> >>>>>>> the object vs a method that creates the object.
> >>>>>>>
> >>>>>>> But again, what problem is this trying to solve? How will this
> make things
> >>>>>>> easier for users?
> >>>>>>>
> >>>>>>> Ralph
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>> On Oct 9, 2019, at 10:42 AM, Matt Sicker <boa...@gmail.com>
> wrote:
> >>>>>>>>
> >>>>>>>> To clarify on the mapping between javax.inject and the existing
> >>>>>>>> annotations, I believe this would work:
> >>>>>>>>
> >>>>>>>> @PluginFactory can be replaced by @Inject
> >>>>>>>> @PluginElement is a @Scope annotation
> >>>>>>>> @PluginAttribute is a @Qualifier annotation
> >>>>>>>> @PluginConfiguration could be a scope or singleton, but it's
> redundant
> >>>>>>>> @PluginNode could be a scope, but it's somewhat redundant
> >>>>>>>> @PluginValue would be a @Qualifier
> >>>>>>>>
> >>>>>>>> On Wed, 9 Oct 2019 at 10:05, Matt Sicker <boa...@gmail.com>
> wrote:
> >>>>>>>>>
> >>>>>>>>> Ok, I see the issue. I won’t add a dependency on the API. I do
> want to
> >>>>>>> try refactoring the 3.x API to use an annotation model similar to
> that.
> >>>>>>> I’ll show a proof of concept sometime soon.
> >>>>>>>>>
> >>>>>>>>> On Tue, Oct 8, 2019 at 18:50, Ralph Goers <
> ralph.go...@dslextreme.com>
> >>>>>>> wrote:
> >>>>>>>>>>
> >>>>>>>>>> I don’t understand. You can’t add javax.inject stuff into our
> >>>>>>> namespace without changing the package name. And if you change the
> package
> >>>>>>> name I don’t see any benefit at all as the current names are much
> clearer.
> >>>>>>>>>>
> >>>>>>>>>> I have no problem with Configurations being a plugin except it
> will
> >>>>>>> currently cause an endless loop as plugins are captured during
> >>>>>>> configuration. So any change you make here is going to be huge.
> >>>>>>>>>>
> >>>>>>>>>> Ralph
> >>>>>>>>>>
> >>>>>>>>>>> On Oct 8, 2019, at 2:23 PM, Matt Sicker <boa...@gmail.com>
> wrote:
> >>>>>>>>>>>
> >>>>>>>>>>> I'm thinking that the old annotations can be supported in
> terms of the
> >>>>>>>>>>> javax.inject API. As for requiring a jar, that's why I've also
> >>>>>>>>>>> suggested just adopting the annotations into our own package
> >>>>>>>>>>> somewhere.
> >>>>>>>>>>>
> >>>>>>>>>>> Either way this is done, my general goal is to untangle other
> areas in
> >>>>>>>>>>> the core API that could benefit from generic DI support. See
> for
> >>>>>>>>>>> example turning Configuration into a plugin.
> >>>>>>>>>>>
> >>>>>>>>>>> On Tue, 8 Oct 2019 at 15:40, Ralph Goers <
> ralph.go...@dslextreme.com>
> >>>>>>> wrote:
> >>>>>>>>>>>>
> >>>>>>>>>>>> I don’t see how that relates. The proposal as I understand it
> is to
> >>>>>>> replace the existing annotations with annotations from
> javax.inject, which
> >>>>>>> would require a JEE jar.
> >>>>>>>>>>>>
> >>>>>>>>>>>> Ralph
> >>>>>>>>>>>>
> >>>>>>>>>>>>> On Oct 8, 2019, at 1:31 PM, Jochen Wiedmann <
> >>>>>>> jochen.wiedm...@gmail.com> wrote:
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> On Tue, Oct 8, 2019 at 10:26 PM Ralph Goers <
> >>>>>>> ralph.go...@dslextreme.com> wrote:
> >>>>>>>>>>>>>>
> >>>>>>>>>>>>>> IIUC this will require a dependency on a Java EE jar?  For
> that
> >>>>>>> reason alone, no.
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> Don't think so. A simple (mostly JSR 330 compliant) provider
> can be
> >>>>>>>>>>>>> implemented in a few classes:
> >>>>>>>>>>>>>
> >>>>>>>>>>>>>
> >>>>>>>
> https://github.com/jochenw/afw/tree/master/afw-core/src/main/java/com/github/jochenw/afw/core/inject/simple
> >>>>>>>>>>>>>
> >>>>>>>>>>>>
> >>>>>>>>>>>>
> >>>>>>>>>>>
> >>>>>>>>>>>
> >>>>>>>>>>> --
> >>>>>>>>>>> Matt Sicker <boa...@gmail.com>
> >>>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>> --
> >>>>>>>>> Matt Sicker <boa...@gmail.com>
> >>>>>>>>
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> --
> >>>>>>>> Matt Sicker <boa...@gmail.com>
> >>>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>> --
> >>>>>> Matt Sicker <boa...@gmail.com>
> >>>>>
> >>>>>
> >>>>>
> >>>>
> >>>>
> >>>
> >>>
> >>> --
> >>> Matt Sicker <boa...@gmail.com>
> >>
> >>
> >>
> >> --
> >> Matt Sicker <boa...@gmail.com>
> >
> >
> >
> > --
> > Matt Sicker <boa...@gmail.com>
> >
>
> --
Matt Sicker <boa...@gmail.com>

Reply via email to