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();
}
}