That sounds like one of the main goals of the DI rewrite I started. To
give more context on the existing system works, the ability to inject
complex objects into plugins is primarily used for mapping nested
configurations. Basically, anything corresponding to an XML element
was injectable into other elements corresponding to the configuration
file structure. Not every component in Log4j is integrated into the
system yet, so there are some pain points like this in 2.x which can
be seen in some things being configurable via system properties while
others have custom plugin elements defined for users to define their
configuration inside. Some of these testability concerns were likely
missed because their underlying code was fast enough to not need
mocks.

Now if you'd like to inject objects instantiated from some arbitrary
point similar to Spring/Guice/etc., that will require a larger
overhaul (likely by rebooting my mean-bean-machine branch at some
point), but if your needs are already structured in a tree, then
@PluginElement is the equivalent of @Inject, while @PluginFactory is
equivalent to @Produces. Depending on your use case, it could be
supportable with the existing plugin system, or it may require
revisiting the DI rewrite, especially if there's wider interest in
completing that.

On Fri, 29 Jan 2021 at 06:56, Volkan Yazıcı <volkan.yaz...@gmail.com> wrote:
>
> Hello,
>
> I am doing some investigation on how to replace statically bound
> JsonTemplateLayout resolvers with plugins. For inspiration I was looking at
> PatternLayout and found the following: PatternLayout calls PatternParser
> ctor, which performs the following:
>
> final PluginManager manager = new PluginManager(converterKey);
> manager.collectPlugins(config == null ? null : config.getPluginPackages());
> final Map<String, PluginType<?>> plugins = manager.getPlugins();
> final Map<String, Class<PatternConverter>> converters = new
> LinkedHashMap<>();
>
> for (final PluginType<?> type : plugins.values()) {
>     try {
>         @SuppressWarnings("unchecked")
>         final Class<PatternConverter> clazz = (Class<PatternConverter>)
> type.getPluginClass();
>         if (filterClass != null && !filterClass.isAssignableFrom(clazz)) {
>             continue;
>         }
>
>
> This got me really puzzled. I was expecting matched plugins to be injected
> into the @PluginFactory ctor of PatternLayout as a parameter of type
> List<PatternConverter> like every other DI system out there. That is,
>
> @PluginFactory
> AwesomeLayout(
>         @PluginConfiguration Configuration config,
>         @PluginElement("converters") List<PatternConverter> converters) {
>     // ...
> }
>
>
> I find usage of PluginManager::new an anti-pattern. For one, it is not
> possible to unit test Pattern{Layout,Parser} by injecting only an isolated
> set of converters. Second, it is not possible to mock PluginManager either.
>
> Is injection of plugins extending a certain interface/class as a
> @PluginFactory ctor parameter something we can introduce to the plugin
> system?
>
> Kind regards.

Reply via email to