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