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

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


The following commit(s) were added to refs/heads/main by this push:
     new e56c480ca2a CAMEL-21140: camel-core - Add init/destroy method support 
for registry bind
e56c480ca2a is described below

commit e56c480ca2a1f4541e6b3a57381b559096934c13
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Aug 29 19:39:12 2024 +0200

    CAMEL-21140: camel-core - Add init/destroy method support for registry bind
---
 .../main/java/org/apache/camel/BindToRegistry.java |  6 ++
 .../impl/engine/DefaultCamelBeanPostProcessor.java | 14 ++++
 ...efaultDependencyInjectionAnnotationFactory.java |  6 +-
 ...ToRegistryBeanInitDestroyMethodServiceTest.java | 89 ++++++++++++++++++++++
 .../org/apache/camel/support/DefaultRegistry.java  |  1 +
 .../camel/support/scan/PackageScanHelper.java      | 16 +++-
 .../injection/AnnotationDependencyInjection.java   |  2 +-
 7 files changed, 129 insertions(+), 5 deletions(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/BindToRegistry.java 
b/core/camel-api/src/main/java/org/apache/camel/BindToRegistry.java
index 15ea5a3cf65..3c68788d609 100644
--- a/core/camel-api/src/main/java/org/apache/camel/BindToRegistry.java
+++ b/core/camel-api/src/main/java/org/apache/camel/BindToRegistry.java
@@ -55,11 +55,17 @@ public @interface BindToRegistry {
 
     /**
      * The optional name of a method to call on the bean instance during 
initialization.
+     *
+     * If the bean is an {@link Service} instance then Camel will 
automatically use start as init method, if none
+     * explicit configured.
      */
     String initMethod() default "";
 
     /**
      * The optional name of a method to call on the bean instance during 
destruction.
+     *
+     * If the bean is an {@link Service} instance then Camel will 
automatically use stop as destroy method, if none
+     * explicit configured.
      */
     String destroyMethod() default "";
 }
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 12c14e21507..6781a0163c0 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
@@ -35,6 +35,7 @@ import org.apache.camel.EndpointInject;
 import org.apache.camel.Produce;
 import org.apache.camel.PropertyInject;
 import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.Service;
 import org.apache.camel.spi.CamelBeanPostProcessor;
 import org.apache.camel.spi.CamelBeanPostProcessorInjector;
 import org.apache.camel.support.DefaultEndpoint;
@@ -539,6 +540,12 @@ public class DefaultCamelBeanPostProcessor implements 
CamelBeanPostProcessor, Ca
         if (unbindEnabled) {
             getOrLookupCamelContext().getRegistry().unbind(name);
         }
+        if (isEmpty(initMethod) && bean instanceof Service) {
+            initMethod = "start";
+        }
+        if (isEmpty(destroyMethod) && bean instanceof Service) {
+            destroyMethod = "stop";
+        }
         // use dependency injection factory to perform the task of binding the 
bean to registry
         Runnable task = 
PluginHelper.getDependencyInjectionAnnotationFactory(getOrLookupCamelContext())
                 .createBindToRegistryFactory(name, bean, clazz, beanName, 
postProcess, initMethod, destroyMethod);
@@ -573,6 +580,13 @@ public class DefaultCamelBeanPostProcessor implements 
CamelBeanPostProcessor, Ca
             value = ReflectionHelper.getField(field, bean);
         }
         if (value != null) {
+            // automatic support Service for init/destroy methods
+            if (isEmpty(initMethod) && bean instanceof Service) {
+                initMethod = "start";
+            }
+            if (isEmpty(destroyMethod) && bean instanceof Service) {
+                destroyMethod = "stop";
+            }
             if (unbindEnabled) {
                 getOrLookupCamelContext().getRegistry().unbind(name);
             }
diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultDependencyInjectionAnnotationFactory.java
 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultDependencyInjectionAnnotationFactory.java
index 6344ae89373..b665e0209fe 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultDependencyInjectionAnnotationFactory.java
+++ 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultDependencyInjectionAnnotationFactory.java
@@ -68,7 +68,11 @@ public class DefaultDependencyInjectionAnnotationFactory
                 Supplier<Object> sup = (Supplier<Object>) bean;
                 camelContext.getRegistry().bind(id, beanType, sup);
             } else {
-                camelContext.getRegistry().bind(id, bean, initMethod, 
destroyMethod);
+                if (initMethod != null || destroyMethod != null) {
+                    camelContext.getRegistry().bind(id, bean, initMethod, 
destroyMethod);
+                } else {
+                    camelContext.getRegistry().bind(id, bean);
+                }
             }
         };
     }
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/impl/BindToRegistryBeanInitDestroyMethodServiceTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/impl/BindToRegistryBeanInitDestroyMethodServiceTest.java
new file mode 100644
index 00000000000..aabfccc7ac5
--- /dev/null
+++ 
b/core/camel-core/src/test/java/org/apache/camel/impl/BindToRegistryBeanInitDestroyMethodServiceTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.impl;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Service;
+import org.apache.camel.support.PluginHelper;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class BindToRegistryBeanInitDestroyMethodServiceTest extends 
ContextTestSupport {
+
+    @BindToRegistry
+    public FooService myFoo() {
+        return new FooService("World");
+    }
+
+    @Test
+    public void testStop() throws Exception {
+        // bean post processing dont run on ContextTestSupport
+        Runnable task = 
PluginHelper.getDependencyInjectionAnnotationFactory(context)
+                .createBindToRegistryFactory("myFoo", myFoo(), 
FooService.class, "myFoo", false, "start", "stop");
+        task.run();
+
+        FooService foo = context.getRegistry().lookupByNameAndType("myFoo", 
FooService.class);
+        assertNotNull(foo);
+        assertEquals("Started World", foo.getMessage());
+
+        // stop camel should trigger destroy
+        context.stop();
+
+        assertEquals("Stopped", foo.getMessage());
+    }
+
+    @Test
+    public void testUnbind() throws Exception {
+        // bean post processing dont run on ContextTestSupport
+        Runnable task = 
PluginHelper.getDependencyInjectionAnnotationFactory(context)
+                .createBindToRegistryFactory("myFoo", myFoo(), 
FooService.class, "myFoo", false, "start", "stop");
+        task.run();
+
+        FooService foo = context.getRegistry().lookupByNameAndType("myFoo", 
FooService.class);
+        assertNotNull(foo);
+        assertEquals("Started World", foo.getMessage());
+
+        // unbind should trigger destroy
+        context.getRegistry().unbind("myFoo");
+        assertEquals("Stopped", foo.getMessage());
+    }
+
+    public static class FooService implements Service {
+
+        private String message;
+
+        public FooService(String message) {
+            this.message = message;
+        }
+
+        public String getMessage() {
+            return message;
+        }
+
+        public void start() {
+            this.message = "Started " + message;
+        }
+
+        public void stop() {
+            this.message = "Stopped";
+        }
+
+    }
+}
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/DefaultRegistry.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/DefaultRegistry.java
index 598a5900534..4b08844eb57 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/DefaultRegistry.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/DefaultRegistry.java
@@ -42,6 +42,7 @@ import org.apache.camel.util.function.Suppliers;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.camel.util.ObjectHelper.isEmpty;
 import static org.apache.camel.util.ObjectHelper.isNotEmpty;
 
 /**
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/scan/PackageScanHelper.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/PackageScanHelper.java
index e405e4550cd..658b5bae758 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/scan/PackageScanHelper.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/PackageScanHelper.java
@@ -26,6 +26,7 @@ import java.util.function.Supplier;
 import org.apache.camel.BindToRegistry;
 import org.apache.camel.CamelContext;
 import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.Service;
 import org.apache.camel.spi.CamelBeanPostProcessor;
 import org.apache.camel.spi.Injector;
 import org.apache.camel.spi.PackageScanClassResolver;
@@ -117,13 +118,22 @@ public class PackageScanHelper {
                                 }
                                 Object bean = entry.getValue();
                                 String beanName = c.getName();
+                                // special for init method as we need to defer 
calling it at a late phase
+                                String initMethod = ann.initMethod();
+                                if (isEmpty(initMethod) && bean instanceof 
Service) {
+                                    initMethod = "start";
+                                }
+                                String destroyMethod = ann.destroyMethod();
+                                if (isEmpty(destroyMethod) && bean instanceof 
Service) {
+                                    destroyMethod = "stop";
+                                }
                                 // - bind to registry if 
@org.apache.camel.BindToRegistry is present
                                 // use dependency injection factory to perform 
the task of binding the bean to registry
                                 Runnable task = 
PluginHelper.getDependencyInjectionAnnotationFactory(camelContext)
-                                        .createBindToRegistryFactory(name, 
bean, c, beanName, false, null, ann.destroyMethod());
+                                        .createBindToRegistryFactory(name, 
bean, c, beanName, false, null, destroyMethod);
                                 // defer calling init methods until dependency 
injection in phase-4 is complete
-                                if (isNotEmpty(ann.initMethod())) {
-                                    initMethods.put(bean, ann.initMethod());
+                                if (isNotEmpty(initMethod)) {
+                                    initMethods.put(bean, initMethod);
                                 }
                                 task.run();
                             }
diff --git 
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/injection/AnnotationDependencyInjection.java
 
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/injection/AnnotationDependencyInjection.java
index fd41ea4ed3e..912d80a7222 100644
--- 
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/injection/AnnotationDependencyInjection.java
+++ 
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/injection/AnnotationDependencyInjection.java
@@ -159,7 +159,7 @@ public final class AnnotationDependencyInjection {
                 camelContext.getRegistry().unbind(beanName);
                 // use dependency injection factory to perform the task of 
binding the bean to registry
                 Runnable task = 
PluginHelper.getDependencyInjectionAnnotationFactory(camelContext)
-                        .createBindToRegistryFactory(name, instance, clazz, 
beanName, false);
+                        .createBindToRegistryFactory(name, instance, clazz, 
beanName, false, bir.initMethod(), bir.destroyMethod());
                 task.run();
             } else {
                 if (bir != null || cfg != null || instance instanceof 
CamelConfiguration) {

Reply via email to