From af194e33e7b58de280f916411a03a36053b5952e Mon Sep 17 00:00:00 2001 From: Santhosh Gandhe <1909520+san81@users.noreply.github.com> Date: Tue, 1 Oct 2024 12:07:15 -0700 Subject: [PATCH] providing an option for the plugins to use Spring DI Signed-off-by: Santhosh Gandhe <1909520+san81@users.noreply.github.com> --- .../model/annotations/DataPrepperPlugin.java | 12 +++++++++++ .../plugin/DefaultPluginFactory.java | 5 ++++- .../plugin/PluginBeanFactoryProvider.java | 21 ++++++++++++++----- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/data-prepper-api/src/main/java/org/opensearch/dataprepper/model/annotations/DataPrepperPlugin.java b/data-prepper-api/src/main/java/org/opensearch/dataprepper/model/annotations/DataPrepperPlugin.java index d94c0d8c19..19bce4fa42 100644 --- a/data-prepper-api/src/main/java/org/opensearch/dataprepper/model/annotations/DataPrepperPlugin.java +++ b/data-prepper-api/src/main/java/org/opensearch/dataprepper/model/annotations/DataPrepperPlugin.java @@ -72,4 +72,16 @@ * @since 1.2 */ Class pluginConfigurationType() default PluginSetting.class; + + /** + * Optional Packages to scan for Data Prepper DI components. + * Plugins provide this list if they want to use Dependency Injection in its module. + * Providing this value, implicitly assumes and initiates plugin specific isolated ApplictionContext. + *

+ * The package names that spring context scans will be picked up by these marker classes. + * + * @return Array of packages to scan + * @since 2.2 + */ + Class[] packagesToScanForDI() default {}; } diff --git a/data-prepper-plugin-framework/src/main/java/org/opensearch/dataprepper/plugin/DefaultPluginFactory.java b/data-prepper-plugin-framework/src/main/java/org/opensearch/dataprepper/plugin/DefaultPluginFactory.java index 1565ce396e..510a3b2179 100644 --- a/data-prepper-plugin-framework/src/main/java/org/opensearch/dataprepper/plugin/DefaultPluginFactory.java +++ b/data-prepper-plugin-framework/src/main/java/org/opensearch/dataprepper/plugin/DefaultPluginFactory.java @@ -13,6 +13,7 @@ import org.opensearch.dataprepper.model.sink.SinkContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.BeanFactory; import org.springframework.context.annotation.DependsOn; import javax.inject.Inject; @@ -115,13 +116,15 @@ private ComponentPluginArgumentsContext getConstructionContext(final PluginS final PluginConfigObservable pluginConfigObservable = pluginConfigurationObservableFactory .createDefaultPluginConfigObservable(pluginConfigurationConverter, pluginConfigurationType, pluginSetting); + BeanFactory beanFactory = + pluginBeanFactoryProvider.initializePluginSpecificIsolatedContextCombinedWithShared(pluginAnnotation); return new ComponentPluginArgumentsContext.Builder() .withPluginSetting(pluginSetting) .withPipelineDescription(pluginSetting) .withPluginConfiguration(configuration) .withPluginFactory(this) .withSinkContext(sinkContext) - .withBeanFactory(pluginBeanFactoryProvider.get()) + .withBeanFactory(beanFactory) .withPluginConfigurationObservable(pluginConfigObservable) .withTypeArgumentSuppliers(applicationContextToTypedSuppliers.getArgumentsSuppliers()) .build(); diff --git a/data-prepper-plugin-framework/src/main/java/org/opensearch/dataprepper/plugin/PluginBeanFactoryProvider.java b/data-prepper-plugin-framework/src/main/java/org/opensearch/dataprepper/plugin/PluginBeanFactoryProvider.java index 66a42eb36a..b2769bf1e6 100644 --- a/data-prepper-plugin-framework/src/main/java/org/opensearch/dataprepper/plugin/PluginBeanFactoryProvider.java +++ b/data-prepper-plugin-framework/src/main/java/org/opensearch/dataprepper/plugin/PluginBeanFactoryProvider.java @@ -5,13 +5,15 @@ package org.opensearch.dataprepper.plugin; +import org.opensearch.dataprepper.model.annotations.DataPrepperPlugin; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.GenericApplicationContext; import javax.inject.Inject; import javax.inject.Named; -import javax.inject.Provider; +import java.util.Arrays; import java.util.Objects; /** @@ -25,7 +27,7 @@ *

publicContext is the root {@link ApplicationContext}

*/ @Named -class PluginBeanFactoryProvider implements Provider { +class PluginBeanFactoryProvider { private final GenericApplicationContext sharedPluginApplicationContext; private final GenericApplicationContext coreApplicationContext; @@ -57,8 +59,17 @@ GenericApplicationContext getCoreApplicationContext() { * instead, a new isolated {@link ApplicationContext} should be created. * @return BeanFactory A BeanFactory that inherits from {@link PluginBeanFactoryProvider#sharedPluginApplicationContext} */ - public BeanFactory get() { - final GenericApplicationContext isolatedPluginApplicationContext = new GenericApplicationContext(sharedPluginApplicationContext); - return isolatedPluginApplicationContext.getBeanFactory(); + public BeanFactory initializePluginSpecificIsolatedContextCombinedWithShared(DataPrepperPlugin pluginAnnotation) { + AnnotationConfigApplicationContext pluginDIContext = new AnnotationConfigApplicationContext(); + if(pluginAnnotation.packagesToScanForDI().length>0) { + // If packages to scan is provided in this plugin annotation, which indicates + // that this plugin is interested in using Dependency Injection isolated for its module + Arrays.stream(pluginAnnotation.packagesToScanForDI()) + .map(Class::getPackageName) + .forEach(pluginDIContext::scan); + pluginDIContext.refresh(); + } + pluginDIContext.setParent(sharedPluginApplicationContext); + return pluginDIContext.getBeanFactory(); } }