You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2022/03/12 06:18:40 UTC

[camel] 05/11: CAMEL-17571: camel-jbang - Support for spring @Autowired/@Value annotations in custom beans

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch CAMEL-17571
in repository https://gitbox.apache.org/repos/asf/camel.git

commit a46c8e7c5bcba5f7fb834d48cb9f42b94e8244fd
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Mar 11 13:03:30 2022 +0100

    CAMEL-17571: camel-jbang - Support for spring @Autowired/@Value annotations in custom beans
---
 .../apache/camel/spi/CamelBeanPostProcessor.java   |  9 +++++
 .../camel/spi/CamelBeanPostProcessorInjector.java  | 32 +++++++++++++++
 .../impl/engine/DefaultCamelBeanPostProcessor.java | 17 ++++++++
 dsl/camel-kamelet-main/pom.xml                     | 10 ++++-
 .../apache/camel/main/SpringAnnotationSupport.java | 46 ++++++++++++++++++++++
 5 files changed, 113 insertions(+), 1 deletion(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/CamelBeanPostProcessor.java b/core/camel-api/src/main/java/org/apache/camel/spi/CamelBeanPostProcessor.java
index 0308f54..1fff611 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/CamelBeanPostProcessor.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/CamelBeanPostProcessor.java
@@ -83,4 +83,13 @@ public interface CamelBeanPostProcessor {
         return false;
     }
 
+    /**
+     * Adds a custom bean post injector
+     *
+     * @param injector the custom injector
+     */
+    default void addCamelBeanPostProjectInjector(CamelBeanPostProcessorInjector injector) {
+        // noop
+    }
+
 }
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/CamelBeanPostProcessorInjector.java b/core/camel-api/src/main/java/org/apache/camel/spi/CamelBeanPostProcessorInjector.java
new file mode 100644
index 0000000..51febcf
--- /dev/null
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/CamelBeanPostProcessorInjector.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.spi;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * Used for custom injection when doing {@link CamelBeanPostProcessor} bean post-processing. Can be used to support
+ * 3rd-party annotations for dependenct injections.
+ */
+public interface CamelBeanPostProcessorInjector {
+
+    void onFieldInject(Field field, Object bean, String beanName);
+
+    void onFieldMethod(Method method, Object bean, String beanName);
+
+}
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultCamelBeanPostProcessor.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultCamelBeanPostProcessor.java
index 3a74646..53fab39 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultCamelBeanPostProcessor.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultCamelBeanPostProcessor.java
@@ -37,6 +37,7 @@ import org.apache.camel.Produce;
 import org.apache.camel.PropertyInject;
 import org.apache.camel.TypeConverter;
 import org.apache.camel.spi.CamelBeanPostProcessor;
+import org.apache.camel.spi.CamelBeanPostProcessorInjector;
 import org.apache.camel.spi.Registry;
 import org.apache.camel.support.DefaultEndpoint;
 import org.apache.camel.util.ReflectionHelper;
@@ -65,6 +66,7 @@ import static org.apache.camel.util.ObjectHelper.isEmpty;
 public class DefaultCamelBeanPostProcessor implements CamelBeanPostProcessor, CamelContextAware {
 
     protected static final Logger LOG = LoggerFactory.getLogger(DefaultCamelBeanPostProcessor.class);
+    protected final List<CamelBeanPostProcessorInjector> beanPostProcessorInjectors = new ArrayList<>();
     protected CamelPostProcessorHelper camelPostProcessorHelper;
     protected CamelContext camelContext;
     protected boolean enabled = true;
@@ -106,6 +108,11 @@ public class DefaultCamelBeanPostProcessor implements CamelBeanPostProcessor, Ca
     }
 
     @Override
+    public void addCamelBeanPostProjectInjector(CamelBeanPostProcessorInjector injector) {
+        this.beanPostProcessorInjectors.add(injector);
+    }
+
+    @Override
     public Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception {
         LOG.trace("Camel bean processing before initialization for bean: {}", beanName);
 
@@ -268,6 +275,11 @@ public class DefaultCamelBeanPostProcessor implements CamelBeanPostProcessor, Ca
                 String uri = produce.value().isEmpty() ? produce.uri() : produce.value();
                 injectField(field, uri, produce.property(), bean, beanName, produce.binding());
             }
+
+            // custom bean injector on the field
+            for (CamelBeanPostProcessorInjector injector : beanPostProcessorInjectors) {
+                injector.onFieldInject(field, bean, beanName);
+            }
         });
     }
 
@@ -323,6 +335,11 @@ public class DefaultCamelBeanPostProcessor implements CamelBeanPostProcessor, Ca
 
             setterInjection(method, bean, beanName);
             getPostProcessorHelper().consumerInjection(method, bean, beanName);
+
+            // custom bean injector on the method
+            for (CamelBeanPostProcessorInjector injector : beanPostProcessorInjectors) {
+                injector.onFieldMethod(method, bean, beanName);
+            }
         });
     }
 
diff --git a/dsl/camel-kamelet-main/pom.xml b/dsl/camel-kamelet-main/pom.xml
index 0236a5f..899e154 100644
--- a/dsl/camel-kamelet-main/pom.xml
+++ b/dsl/camel-kamelet-main/pom.xml
@@ -113,7 +113,15 @@
             <exclusions>
                 <exclusion>
                     <groupId>org.springframework</groupId>
-                    <artifactId>*</artifactId>
+                    <artifactId>spring-aop</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.springframework</groupId>
+                    <artifactId>spring-core</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.springframework</groupId>
+                    <artifactId>spring-expression</artifactId>
                 </exclusion>
             </exclusions>
         </dependency>
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/SpringAnnotationSupport.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/SpringAnnotationSupport.java
index 26392b0..0f0e8a9 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/SpringAnnotationSupport.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/SpringAnnotationSupport.java
@@ -16,11 +16,20 @@
  */
 package org.apache.camel.main;
 
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
 import org.apache.camel.CamelContext;
 import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.dsl.support.CompilePostProcessor;
+import org.apache.camel.impl.engine.CamelPostProcessorHelper;
 import org.apache.camel.spi.CamelBeanPostProcessor;
+import org.apache.camel.spi.CamelBeanPostProcessorInjector;
 import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.ReflectionHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Service;
 
@@ -31,6 +40,8 @@ public final class SpringAnnotationSupport {
 
     public static void registerSpringSupport(CamelContext context) {
         context.getRegistry().bind("SpringAnnotationCompilePostProcessor", new SpringAnnotationCompilePostProcessor());
+        context.adapt(ExtendedCamelContext.class).getBeanPostProcessor()
+                .addCamelBeanPostProjectInjector(new SpringBeanPostProcessorInjector(context));
     }
 
     private static class SpringAnnotationCompilePostProcessor implements CompilePostProcessor {
@@ -62,4 +73,39 @@ public final class SpringAnnotationSupport {
             }
         }
     }
+
+    private static class SpringBeanPostProcessorInjector implements CamelBeanPostProcessorInjector {
+
+        private final CamelContext context;
+        private final CamelPostProcessorHelper helper;
+
+        public SpringBeanPostProcessorInjector(CamelContext context) {
+            this.context = context;
+            this.helper = new CamelPostProcessorHelper(context);
+        }
+
+        @Override
+        public void onFieldInject(Field field, Object bean, String beanName) {
+            Autowired autowired = field.getAnnotation(Autowired.class);
+            if (autowired != null) {
+                String name = null;
+                Qualifier qualifier = field.getAnnotation(Qualifier.class);
+                if (qualifier != null) {
+                    name = qualifier.value();
+                }
+                ReflectionHelper.setField(field, bean,
+                        helper.getInjectionBeanValue(field.getType(), name));
+            }
+            Value value = field.getAnnotation(Value.class);
+            if (value != null) {
+                ReflectionHelper.setField(field, bean,
+                        helper.getInjectionPropertyValue(field.getType(), value.value(), null, null, bean, beanName));
+            }
+        }
+
+        @Override
+        public void onFieldMethod(Method method, Object bean, String beanName) {
+
+        }
+    }
 }