You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@logging.apache.org by Matt Sicker <bo...@gmail.com> on 2019/11/02 21:04:58 UTC

Re: [Java] Proposal: replacing plugin annotations with javax.inject ones

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 <bo...@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 <ra...@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 <ra...@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 <bo...@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 <ra...@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 <bo...@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 <bo...@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 <ra...@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 <bo...@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 <ra...@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.wiedmann@gmail.com> wrote:
> > >>>>>>>>>
> > >>>>>>>>> On Tue, Oct 8, 2019 at 10:26 PM Ralph Goers <
> > >>> ralph.goers@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 <bo...@gmail.com>
> > >>>>>>>
> > >>>>>>
> > >>>>>>
> > >>>>> --
> > >>>>> Matt Sicker <bo...@gmail.com>
> > >>>>
> > >>>>
> > >>>>
> > >>>> --
> > >>>> Matt Sicker <bo...@gmail.com>
> > >>>>
> > >>>
> > >>>
> > >>> --
> > >> Matt Sicker <bo...@gmail.com>
> > >
> > >
> > >
> >
> >
>
>
> --
> Matt Sicker <bo...@gmail.com>



-- 
Matt Sicker <bo...@gmail.com>

Re: [Java] Proposal: replacing plugin annotations with javax.inject ones

Posted by Matt Sicker <bo...@gmail.com>.
Another idea that I had while looking through CDI is supporting a unit
of work logging feature LOG4J2-1630 [1] might be supportable with
something similar to @ConversationScoped in CDI [2].

[1]: https://issues.apache.org/jira/browse/LOG4J2-1630
[2]: https://docs.jboss.org/cdi/api/2.0/javax/enterprise/context/ConversationScoped.html

On Sat, 9 Nov 2019 at 11:46, Matt Sicker <bo...@gmail.com> wrote:
>
> ScriptRef is a fairly simple conversion: you'd either add @Inject on
> its current constructor (we'd make ScriptManager a singleton or
> similar scope) and potentially adding a configuration scope annotation
> on the name parameter (the default scope in javax.inject is supposed
> to be effectively a prototype scope), or you'd change the
> Configuration parameter in the factory method to be ScriptManager
> instead. No scope annotation would likely be required because there
> would only be a single ScriptManager to choose from the available
> scopes.
>
> CronTriggeringPolicy could be likewise update the same way. This would
> be even easier to support by adding a TypeConverter for
> CronExpression.
>
> ScriptPatternSelector is slightly more interesting. The StrSubstitutor
> can be injected directly (probably a configuration-scope object). I'm
> not currently sure how to model the configuration properties since
> it's just a string->string map currently, though we could always add a
> wrapper class there if necessary.
>
> For AbstractLayout, the configuration can be replaced by the injected
> StrSubstitutor as well. AbstractStringLayout relies on the root logger
> config, and this is one of those scenarios where I expect the
> injection API to really show off features. This would be a
> LoggerConfig injection with some sort of qualifier.
>
> As for Lookup overhead, I don't imagine this system to introduce much
> overhead (if any at all once JIT'd) since constructors and such are
> assembled at startup to an extent. The static code generation version
> should further avoid overhead as it would just be directly setting up
> objects without reflection.
>
> On Tue, 5 Nov 2019 at 11:25, Matt Sicker <bo...@gmail.com> wrote:
> >
> > Yes, these sound like great starting points. I'll work on a proof of
> > concept of what I imagine the classes can look like after implementing
> > the new injection system.
> >
> > On Mon, 4 Nov 2019 at 22:48, Ralph Goers <ra...@dslextreme.com> wrote:
> > >
> > > PatternLayout and RFC5424Layout use the Configuration to pass to Converters, primarily so they can use the Interpolator.  CronTriggeringPolicy and IdlePurgePolicy access the Configuration to get to the ConfigurationScheduler.  ScriptPatternSelector, and all other Script plugins, accesses the Configuration to ge to the ScriptManager.
> > >
> > > Note that Lookups all have no-arg constructors but some of them, such as Log4jLookup, need access to the Configuration. They do that by extending AbstractConfigurationAwareLookup. That could obviously be replaced with an annotation to perform the injection, although checking for the interface probably involves less overhead.
> > >
> > > Hopefully this is what you are looking for. I am sure there are other cases though.
> > >
> > > Ralph
> > >
> > >
> > >
> > > > On Nov 4, 2019, at 1:18 PM, Matt Sicker <bo...@gmail.com> wrote:
> > > >
> > > > Do you have any example plugins that might be a good example to showcase
> > > > the scopes and qualifiers model? Preferably a plugin that injects a
> > > > Configuration in order to obtain some other services or other ad hoc type
> > > > plugins. Any plugin using just attributes (and elements and values) would
> > > > be trivial to convert to the updated system (they’d likely be unchanged
> > > > depending on how I model stereotypes; this is one area I intend to
> > > > significantly diverge from CDI and act more like Spring where you can make
> > > > stereotypes out of almost any annotation instead of just qualifiers and a
> > > > single scope), so a plugin that needs injected values from elsewhere would
> > > > probably showcase this idea best.
> > > >
> > > > On Sun, Nov 3, 2019 at 23:30 Matt Sicker <bo...@gmail.com> wrote:
> > > >
> > > >> 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 <ra...@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 <bo...@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 <bo...@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 <bo...@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 <ra...@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 <ra...@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 <bo...@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.goers@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 <bo...@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 <bo...@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.goers@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 <bo...@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.goers@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.wiedmann@gmail.com> wrote:
> > > >>>>>>>>>>>>>>>>
> > > >>>>>>>>>>>>>>>> On Tue, Oct 8, 2019 at 10:26 PM Ralph Goers <
> > > >>>>>>>>>> ralph.goers@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 <bo...@gmail.com>
> > > >>>>>>>>>>>>>>
> > > >>>>>>>>>>>>>
> > > >>>>>>>>>>>>>
> > > >>>>>>>>>>>> --
> > > >>>>>>>>>>>> Matt Sicker <bo...@gmail.com>
> > > >>>>>>>>>>>
> > > >>>>>>>>>>>
> > > >>>>>>>>>>>
> > > >>>>>>>>>>> --
> > > >>>>>>>>>>> Matt Sicker <bo...@gmail.com>
> > > >>>>>>>>>>>
> > > >>>>>>>>>>
> > > >>>>>>>>>>
> > > >>>>>>>>>> --
> > > >>>>>>>>> Matt Sicker <bo...@gmail.com>
> > > >>>>>>>>
> > > >>>>>>>>
> > > >>>>>>>>
> > > >>>>>>>
> > > >>>>>>>
> > > >>>>>>
> > > >>>>>>
> > > >>>>>> --
> > > >>>>>> Matt Sicker <bo...@gmail.com>
> > > >>>>>
> > > >>>>>
> > > >>>>>
> > > >>>>> --
> > > >>>>> Matt Sicker <bo...@gmail.com>
> > > >>>>
> > > >>>>
> > > >>>>
> > > >>>> --
> > > >>>> Matt Sicker <bo...@gmail.com>
> > > >>>>
> > > >>>
> > > >>> --
> > > >> Matt Sicker <bo...@gmail.com>
> > > >>
> > > > --
> > > > Matt Sicker <bo...@gmail.com>
> > >
> > >
> >
> >
> > --
> > Matt Sicker <bo...@gmail.com>
>
>
>
> --
> Matt Sicker <bo...@gmail.com>



-- 
Matt Sicker <bo...@gmail.com>

Re: [Java] Proposal: replacing plugin annotations with javax.inject ones

Posted by Matt Sicker <bo...@gmail.com>.
ScriptRef is a fairly simple conversion: you'd either add @Inject on
its current constructor (we'd make ScriptManager a singleton or
similar scope) and potentially adding a configuration scope annotation
on the name parameter (the default scope in javax.inject is supposed
to be effectively a prototype scope), or you'd change the
Configuration parameter in the factory method to be ScriptManager
instead. No scope annotation would likely be required because there
would only be a single ScriptManager to choose from the available
scopes.

CronTriggeringPolicy could be likewise update the same way. This would
be even easier to support by adding a TypeConverter for
CronExpression.

ScriptPatternSelector is slightly more interesting. The StrSubstitutor
can be injected directly (probably a configuration-scope object). I'm
not currently sure how to model the configuration properties since
it's just a string->string map currently, though we could always add a
wrapper class there if necessary.

For AbstractLayout, the configuration can be replaced by the injected
StrSubstitutor as well. AbstractStringLayout relies on the root logger
config, and this is one of those scenarios where I expect the
injection API to really show off features. This would be a
LoggerConfig injection with some sort of qualifier.

As for Lookup overhead, I don't imagine this system to introduce much
overhead (if any at all once JIT'd) since constructors and such are
assembled at startup to an extent. The static code generation version
should further avoid overhead as it would just be directly setting up
objects without reflection.

On Tue, 5 Nov 2019 at 11:25, Matt Sicker <bo...@gmail.com> wrote:
>
> Yes, these sound like great starting points. I'll work on a proof of
> concept of what I imagine the classes can look like after implementing
> the new injection system.
>
> On Mon, 4 Nov 2019 at 22:48, Ralph Goers <ra...@dslextreme.com> wrote:
> >
> > PatternLayout and RFC5424Layout use the Configuration to pass to Converters, primarily so they can use the Interpolator.  CronTriggeringPolicy and IdlePurgePolicy access the Configuration to get to the ConfigurationScheduler.  ScriptPatternSelector, and all other Script plugins, accesses the Configuration to ge to the ScriptManager.
> >
> > Note that Lookups all have no-arg constructors but some of them, such as Log4jLookup, need access to the Configuration. They do that by extending AbstractConfigurationAwareLookup. That could obviously be replaced with an annotation to perform the injection, although checking for the interface probably involves less overhead.
> >
> > Hopefully this is what you are looking for. I am sure there are other cases though.
> >
> > Ralph
> >
> >
> >
> > > On Nov 4, 2019, at 1:18 PM, Matt Sicker <bo...@gmail.com> wrote:
> > >
> > > Do you have any example plugins that might be a good example to showcase
> > > the scopes and qualifiers model? Preferably a plugin that injects a
> > > Configuration in order to obtain some other services or other ad hoc type
> > > plugins. Any plugin using just attributes (and elements and values) would
> > > be trivial to convert to the updated system (they’d likely be unchanged
> > > depending on how I model stereotypes; this is one area I intend to
> > > significantly diverge from CDI and act more like Spring where you can make
> > > stereotypes out of almost any annotation instead of just qualifiers and a
> > > single scope), so a plugin that needs injected values from elsewhere would
> > > probably showcase this idea best.
> > >
> > > On Sun, Nov 3, 2019 at 23:30 Matt Sicker <bo...@gmail.com> wrote:
> > >
> > >> 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 <ra...@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 <bo...@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 <bo...@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 <bo...@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 <ra...@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 <ra...@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 <bo...@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.goers@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 <bo...@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 <bo...@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.goers@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 <bo...@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.goers@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.wiedmann@gmail.com> wrote:
> > >>>>>>>>>>>>>>>>
> > >>>>>>>>>>>>>>>> On Tue, Oct 8, 2019 at 10:26 PM Ralph Goers <
> > >>>>>>>>>> ralph.goers@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 <bo...@gmail.com>
> > >>>>>>>>>>>>>>
> > >>>>>>>>>>>>>
> > >>>>>>>>>>>>>
> > >>>>>>>>>>>> --
> > >>>>>>>>>>>> Matt Sicker <bo...@gmail.com>
> > >>>>>>>>>>>
> > >>>>>>>>>>>
> > >>>>>>>>>>>
> > >>>>>>>>>>> --
> > >>>>>>>>>>> Matt Sicker <bo...@gmail.com>
> > >>>>>>>>>>>
> > >>>>>>>>>>
> > >>>>>>>>>>
> > >>>>>>>>>> --
> > >>>>>>>>> Matt Sicker <bo...@gmail.com>
> > >>>>>>>>
> > >>>>>>>>
> > >>>>>>>>
> > >>>>>>>
> > >>>>>>>
> > >>>>>>
> > >>>>>>
> > >>>>>> --
> > >>>>>> Matt Sicker <bo...@gmail.com>
> > >>>>>
> > >>>>>
> > >>>>>
> > >>>>> --
> > >>>>> Matt Sicker <bo...@gmail.com>
> > >>>>
> > >>>>
> > >>>>
> > >>>> --
> > >>>> Matt Sicker <bo...@gmail.com>
> > >>>>
> > >>>
> > >>> --
> > >> Matt Sicker <bo...@gmail.com>
> > >>
> > > --
> > > Matt Sicker <bo...@gmail.com>
> >
> >
>
>
> --
> Matt Sicker <bo...@gmail.com>



-- 
Matt Sicker <bo...@gmail.com>

Re: [Java] Proposal: replacing plugin annotations with javax.inject ones

Posted by Matt Sicker <bo...@gmail.com>.
Yes, these sound like great starting points. I'll work on a proof of
concept of what I imagine the classes can look like after implementing
the new injection system.

On Mon, 4 Nov 2019 at 22:48, Ralph Goers <ra...@dslextreme.com> wrote:
>
> PatternLayout and RFC5424Layout use the Configuration to pass to Converters, primarily so they can use the Interpolator.  CronTriggeringPolicy and IdlePurgePolicy access the Configuration to get to the ConfigurationScheduler.  ScriptPatternSelector, and all other Script plugins, accesses the Configuration to ge to the ScriptManager.
>
> Note that Lookups all have no-arg constructors but some of them, such as Log4jLookup, need access to the Configuration. They do that by extending AbstractConfigurationAwareLookup. That could obviously be replaced with an annotation to perform the injection, although checking for the interface probably involves less overhead.
>
> Hopefully this is what you are looking for. I am sure there are other cases though.
>
> Ralph
>
>
>
> > On Nov 4, 2019, at 1:18 PM, Matt Sicker <bo...@gmail.com> wrote:
> >
> > Do you have any example plugins that might be a good example to showcase
> > the scopes and qualifiers model? Preferably a plugin that injects a
> > Configuration in order to obtain some other services or other ad hoc type
> > plugins. Any plugin using just attributes (and elements and values) would
> > be trivial to convert to the updated system (they’d likely be unchanged
> > depending on how I model stereotypes; this is one area I intend to
> > significantly diverge from CDI and act more like Spring where you can make
> > stereotypes out of almost any annotation instead of just qualifiers and a
> > single scope), so a plugin that needs injected values from elsewhere would
> > probably showcase this idea best.
> >
> > On Sun, Nov 3, 2019 at 23:30 Matt Sicker <bo...@gmail.com> wrote:
> >
> >> 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 <ra...@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 <bo...@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 <bo...@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 <bo...@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 <ra...@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 <ra...@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 <bo...@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.goers@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 <bo...@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 <bo...@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.goers@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 <bo...@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.goers@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.wiedmann@gmail.com> wrote:
> >>>>>>>>>>>>>>>>
> >>>>>>>>>>>>>>>> On Tue, Oct 8, 2019 at 10:26 PM Ralph Goers <
> >>>>>>>>>> ralph.goers@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 <bo...@gmail.com>
> >>>>>>>>>>>>>>
> >>>>>>>>>>>>>
> >>>>>>>>>>>>>
> >>>>>>>>>>>> --
> >>>>>>>>>>>> Matt Sicker <bo...@gmail.com>
> >>>>>>>>>>>
> >>>>>>>>>>>
> >>>>>>>>>>>
> >>>>>>>>>>> --
> >>>>>>>>>>> Matt Sicker <bo...@gmail.com>
> >>>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>> --
> >>>>>>>>> Matt Sicker <bo...@gmail.com>
> >>>>>>>>
> >>>>>>>>
> >>>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>
> >>>>>>
> >>>>>> --
> >>>>>> Matt Sicker <bo...@gmail.com>
> >>>>>
> >>>>>
> >>>>>
> >>>>> --
> >>>>> Matt Sicker <bo...@gmail.com>
> >>>>
> >>>>
> >>>>
> >>>> --
> >>>> Matt Sicker <bo...@gmail.com>
> >>>>
> >>>
> >>> --
> >> Matt Sicker <bo...@gmail.com>
> >>
> > --
> > Matt Sicker <bo...@gmail.com>
>
>


-- 
Matt Sicker <bo...@gmail.com>

Re: [Java] Proposal: replacing plugin annotations with javax.inject ones

Posted by Ralph Goers <ra...@dslextreme.com>.
PatternLayout and RFC5424Layout use the Configuration to pass to Converters, primarily so they can use the Interpolator.  CronTriggeringPolicy and IdlePurgePolicy access the Configuration to get to the ConfigurationScheduler.  ScriptPatternSelector, and all other Script plugins, accesses the Configuration to ge to the ScriptManager. 

Note that Lookups all have no-arg constructors but some of them, such as Log4jLookup, need access to the Configuration. They do that by extending AbstractConfigurationAwareLookup. That could obviously be replaced with an annotation to perform the injection, although checking for the interface probably involves less overhead.

Hopefully this is what you are looking for. I am sure there are other cases though.

Ralph



> On Nov 4, 2019, at 1:18 PM, Matt Sicker <bo...@gmail.com> wrote:
> 
> Do you have any example plugins that might be a good example to showcase
> the scopes and qualifiers model? Preferably a plugin that injects a
> Configuration in order to obtain some other services or other ad hoc type
> plugins. Any plugin using just attributes (and elements and values) would
> be trivial to convert to the updated system (they’d likely be unchanged
> depending on how I model stereotypes; this is one area I intend to
> significantly diverge from CDI and act more like Spring where you can make
> stereotypes out of almost any annotation instead of just qualifiers and a
> single scope), so a plugin that needs injected values from elsewhere would
> probably showcase this idea best.
> 
> On Sun, Nov 3, 2019 at 23:30 Matt Sicker <bo...@gmail.com> wrote:
> 
>> 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 <ra...@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 <bo...@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 <bo...@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 <bo...@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 <ra...@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 <ra...@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 <bo...@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.goers@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 <bo...@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 <bo...@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.goers@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 <bo...@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.goers@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.wiedmann@gmail.com> wrote:
>>>>>>>>>>>>>>>> 
>>>>>>>>>>>>>>>> On Tue, Oct 8, 2019 at 10:26 PM Ralph Goers <
>>>>>>>>>> ralph.goers@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 <bo...@gmail.com>
>>>>>>>>>>>>>> 
>>>>>>>>>>>>> 
>>>>>>>>>>>>> 
>>>>>>>>>>>> --
>>>>>>>>>>>> Matt Sicker <bo...@gmail.com>
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> --
>>>>>>>>>>> Matt Sicker <bo...@gmail.com>
>>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>> --
>>>>>>>>> Matt Sicker <bo...@gmail.com>
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> --
>>>>>> Matt Sicker <bo...@gmail.com>
>>>>> 
>>>>> 
>>>>> 
>>>>> --
>>>>> Matt Sicker <bo...@gmail.com>
>>>> 
>>>> 
>>>> 
>>>> --
>>>> Matt Sicker <bo...@gmail.com>
>>>> 
>>> 
>>> --
>> Matt Sicker <bo...@gmail.com>
>> 
> -- 
> Matt Sicker <bo...@gmail.com>



Re: [Java] Proposal: replacing plugin annotations with javax.inject ones

Posted by Matt Sicker <bo...@gmail.com>.
Do you have any example plugins that might be a good example to showcase
the scopes and qualifiers model? Preferably a plugin that injects a
Configuration in order to obtain some other services or other ad hoc type
plugins. Any plugin using just attributes (and elements and values) would
be trivial to convert to the updated system (they’d likely be unchanged
depending on how I model stereotypes; this is one area I intend to
significantly diverge from CDI and act more like Spring where you can make
stereotypes out of almost any annotation instead of just qualifiers and a
single scope), so a plugin that needs injected values from elsewhere would
probably showcase this idea best.

On Sun, Nov 3, 2019 at 23:30 Matt Sicker <bo...@gmail.com> wrote:

> 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 <ra...@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 <bo...@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 <bo...@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 <bo...@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 <ra...@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 <ra...@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 <bo...@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.goers@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 <bo...@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 <bo...@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.goers@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 <bo...@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.goers@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.wiedmann@gmail.com> wrote:
>> >>>>>>>>>>>>>
>> >>>>>>>>>>>>> On Tue, Oct 8, 2019 at 10:26 PM Ralph Goers <
>> >>>>>>> ralph.goers@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 <bo...@gmail.com>
>> >>>>>>>>>>>
>> >>>>>>>>>>
>> >>>>>>>>>>
>> >>>>>>>>> --
>> >>>>>>>>> Matt Sicker <bo...@gmail.com>
>> >>>>>>>>
>> >>>>>>>>
>> >>>>>>>>
>> >>>>>>>> --
>> >>>>>>>> Matt Sicker <bo...@gmail.com>
>> >>>>>>>>
>> >>>>>>>
>> >>>>>>>
>> >>>>>>> --
>> >>>>>> Matt Sicker <bo...@gmail.com>
>> >>>>>
>> >>>>>
>> >>>>>
>> >>>>
>> >>>>
>> >>>
>> >>>
>> >>> --
>> >>> Matt Sicker <bo...@gmail.com>
>> >>
>> >>
>> >>
>> >> --
>> >> Matt Sicker <bo...@gmail.com>
>> >
>> >
>> >
>> > --
>> > Matt Sicker <bo...@gmail.com>
>> >
>>
>> --
> Matt Sicker <bo...@gmail.com>
>
-- 
Matt Sicker <bo...@gmail.com>

Re: [Java] Proposal: replacing plugin annotations with javax.inject ones

Posted by Matt Sicker <bo...@gmail.com>.
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 <ra...@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 <bo...@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 <bo...@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 <bo...@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 <ra...@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 <ra...@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 <bo...@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.goers@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 <bo...@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 <bo...@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.goers@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 <bo...@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.goers@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.wiedmann@gmail.com> wrote:
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> On Tue, Oct 8, 2019 at 10:26 PM Ralph Goers <
> >>>>>>> ralph.goers@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 <bo...@gmail.com>
> >>>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>> --
> >>>>>>>>> Matt Sicker <bo...@gmail.com>
> >>>>>>>>
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> --
> >>>>>>>> Matt Sicker <bo...@gmail.com>
> >>>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>> --
> >>>>>> Matt Sicker <bo...@gmail.com>
> >>>>>
> >>>>>
> >>>>>
> >>>>
> >>>>
> >>>
> >>>
> >>> --
> >>> Matt Sicker <bo...@gmail.com>
> >>
> >>
> >>
> >> --
> >> Matt Sicker <bo...@gmail.com>
> >
> >
> >
> > --
> > Matt Sicker <bo...@gmail.com>
> >
>
> --
Matt Sicker <bo...@gmail.com>

Re: [Java] Proposal: replacing plugin annotations with javax.inject ones

Posted by Ralph Goers <ra...@dslextreme.com>.
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 <bo...@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 <bo...@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 <bo...@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 <ra...@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 <ra...@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 <bo...@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 <ra...@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 <bo...@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 <bo...@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 <ra...@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 <bo...@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 <ra...@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.wiedmann@gmail.com> wrote:
>>>>>>>>>>>>> 
>>>>>>>>>>>>> On Tue, Oct 8, 2019 at 10:26 PM Ralph Goers <
>>>>>>> ralph.goers@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 <bo...@gmail.com>
>>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>> --
>>>>>>>>> Matt Sicker <bo...@gmail.com>
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>>>>> --
>>>>>>>> Matt Sicker <bo...@gmail.com>
>>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> --
>>>>>> Matt Sicker <bo...@gmail.com>
>>>>> 
>>>>> 
>>>>> 
>>>> 
>>>> 
>>> 
>>> 
>>> --
>>> Matt Sicker <bo...@gmail.com>
>> 
>> 
>> 
>> --
>> Matt Sicker <bo...@gmail.com>
> 
> 
> 
> -- 
> Matt Sicker <bo...@gmail.com>
> 


Re: [Java] Proposal: replacing plugin annotations with javax.inject ones

Posted by Matt Sicker <bo...@gmail.com>.
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 <bo...@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 <bo...@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 <ra...@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 <ra...@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 <bo...@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 <ra...@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 <bo...@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 <bo...@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 <ra...@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 <bo...@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 <ra...@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.wiedmann@gmail.com> wrote:
> > > >>>>>>>>>
> > > >>>>>>>>> On Tue, Oct 8, 2019 at 10:26 PM Ralph Goers <
> > > >>> ralph.goers@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 <bo...@gmail.com>
> > > >>>>>>>
> > > >>>>>>
> > > >>>>>>
> > > >>>>> --
> > > >>>>> Matt Sicker <bo...@gmail.com>
> > > >>>>
> > > >>>>
> > > >>>>
> > > >>>> --
> > > >>>> Matt Sicker <bo...@gmail.com>
> > > >>>>
> > > >>>
> > > >>>
> > > >>> --
> > > >> Matt Sicker <bo...@gmail.com>
> > > >
> > > >
> > > >
> > >
> > >
> >
> >
> > --
> > Matt Sicker <bo...@gmail.com>
>
>
>
> --
> Matt Sicker <bo...@gmail.com>



-- 
Matt Sicker <bo...@gmail.com>