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

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

commit d9e6838c6b2ba140ca9c1b9471736c9cf41abb2f
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Thu Aug 22 11:48:11 2019 +0200

    CAMEL-13870: Fast property configuration of Camel endpoints. Work in 
progress.
---
 .../org/apache/camel/ExtendedCamelContext.java     |  5 +++
 .../org/apache/camel/spi/BeanIntrospection.java    |  8 +++-
 .../camel/impl/engine/AbstractCamelContext.java    | 22 ++++++++---
 .../impl/engine/DefaultBeanIntrospection.java      | 35 ++++++++++++++++-
 .../org/apache/camel/impl/DefaultCamelContext.java |  7 ++++
 .../mbean/ManagedBeanIntrospectionMBean.java       | 26 +++++++++++++
 .../management/JmxManagementLifecycleStrategy.java |  4 ++
 .../management/mbean/ManagedBeanIntrospection.java | 45 ++++++++++++++++++++++
 examples/camel-example-management/pom.xml          |  5 +++
 9 files changed, 149 insertions(+), 8 deletions(-)

diff --git 
a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java 
b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
index 6ffdcea..7f85e8f 100644
--- a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
@@ -339,4 +339,9 @@ public interface ExtendedCamelContext extends CamelContext {
      */
     BeanIntrospection getBeanIntrospection();
 
+    /**
+     * Sets a custom {@link BeanIntrospection}.
+     */
+    void setBeanIntrospection(BeanIntrospection beanIntrospection);
+
 }
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/BeanIntrospection.java 
b/core/camel-api/src/main/java/org/apache/camel/spi/BeanIntrospection.java
index 805b98d..406210e 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/BeanIntrospection.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/BeanIntrospection.java
@@ -22,6 +22,7 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.StaticService;
 import org.apache.camel.TypeConverter;
 
 // TODO: Keep only public used methods so we can remove the tech debt
@@ -32,7 +33,12 @@ import org.apache.camel.TypeConverter;
  *
  * End users should favour using 
org.apache.camel.support.PropertyBindingSupport instead.
  */
-public interface BeanIntrospection {
+public interface BeanIntrospection extends StaticService {
+
+    /**
+     * Number of times bean introspection has been invoked
+     */
+    long getInvokedCounter();
 
     boolean isGetter(Method method);
 
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
 
b/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index 2211f86..43b229c 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ 
b/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -141,7 +141,6 @@ import org.apache.camel.spi.ValidatorRegistry;
 import org.apache.camel.support.CamelContextHelper;
 import org.apache.camel.support.EndpointHelper;
 import org.apache.camel.support.EventHelper;
-import org.apache.camel.support.IntrospectionSupport;
 import org.apache.camel.support.OrderedComparator;
 import org.apache.camel.support.ProcessorEndpoint;
 import org.apache.camel.support.ResolverHelper;
@@ -255,7 +254,7 @@ public abstract class AbstractCamelContext extends 
ServiceSupport implements Ext
     private volatile UnitOfWorkFactory unitOfWorkFactory;
     private volatile RouteController routeController;
     private volatile ScheduledExecutorService errorHandlerExecutorService;
-    private final BeanIntrospection beanIntrospection = new 
DefaultBeanIntrospection();
+    private volatile BeanIntrospection beanIntrospection;
     private final DeferServiceFactory deferServiceFactory = new 
DefaultDeferServiceFactory();
     private final AnnotationBasedProcessorFactory 
annotationBasedProcessorFactory = new DefaultAnnotationBasedProcessorFactory();
 
@@ -2772,10 +2771,6 @@ public abstract class AbstractCamelContext extends 
ServiceSupport implements Ext
         // stop the lazy created so they can be re-created on restart
         forceStopLazyInitialization();
 
-        // stop to clear introspection cache
-        ServiceHelper.stopService(beanIntrospection);
-        IntrospectionSupport.stop();
-
         if (log.isInfoEnabled()) {
             log.info("Apache Camel " + getVersion() + " (CamelContext: " + 
getName() + ") uptime {}", getUptime());
             log.info("Apache Camel {} (CamelContext: {}) is shutdown in {}", 
getVersion(), getName(), TimeUtils.printDuration(stopWatch.taken()));
@@ -3317,6 +3312,7 @@ public abstract class AbstractCamelContext extends 
ServiceSupport implements Ext
         getPollingConsumerServicePool();
         getRestRegistryFactory();
         getReactiveExecutor();
+        getBeanIntrospection();
 
         if (isTypeConverterStatisticsEnabled() != null) {
             
getTypeConverterRegistry().getStatistics().setStatisticsEnabled(isTypeConverterStatisticsEnabled());
@@ -3659,10 +3655,22 @@ public abstract class AbstractCamelContext extends 
ServiceSupport implements Ext
 
     @Override
     public BeanIntrospection getBeanIntrospection() {
+        if (beanIntrospection == null) {
+            synchronized (lock) {
+                if (beanIntrospection == null) {
+                    setBeanIntrospection(createBeanIntrospection());
+                }
+            }
+        }
         return beanIntrospection;
     }
 
     @Override
+    public void setBeanIntrospection(BeanIntrospection beanIntrospection) {
+        this.beanIntrospection = doAddService(beanIntrospection);
+    }
+
+    @Override
     public void setAutoStartup(Boolean autoStartup) {
         this.autoStartup = autoStartup;
     }
@@ -4222,6 +4230,8 @@ public abstract class AbstractCamelContext extends 
ServiceSupport implements Ext
 
     protected abstract BeanProcessorFactory createBeanProcessorFactory();
 
+    protected abstract BeanIntrospection createBeanIntrospection();
+
     protected abstract Tracer createTracer();
 
     protected abstract LanguageResolver createLanguageResolver();
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultBeanIntrospection.java
 
b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultBeanIntrospection.java
index 768ff50..162b0d4 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultBeanIntrospection.java
+++ 
b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultBeanIntrospection.java
@@ -20,17 +20,27 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.TypeConverter;
 import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.support.IntrospectionSupport;
 import org.apache.camel.support.service.ServiceSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @SuppressWarnings("deprecation")
 public class DefaultBeanIntrospection extends ServiceSupport implements 
BeanIntrospection {
 
-    // TODO: Add runtime statistics so we can report how much Java reflection 
has been in use
+    private static final Logger LOG = 
LoggerFactory.getLogger(DefaultBeanIntrospection.class);
+
+    private final AtomicLong invoked = new AtomicLong();
+
+    @Override
+    public long getInvokedCounter() {
+        return invoked.get();
+    }
 
     @Override
     public boolean isGetter(Method method) {
@@ -64,11 +74,13 @@ public class DefaultBeanIntrospection extends 
ServiceSupport implements BeanIntr
 
     @Override
     public boolean getProperties(Object target, Map<String, Object> 
properties, String optionPrefix) {
+        invoked.incrementAndGet();
         return IntrospectionSupport.getProperties(target, properties, 
optionPrefix);
     }
 
     @Override
     public boolean getProperties(Object target, Map<String, Object> 
properties, String optionPrefix, boolean includeNull) {
+        invoked.incrementAndGet();
         return IntrospectionSupport.getProperties(target, properties, 
optionPrefix, includeNull);
     }
 
@@ -79,48 +91,57 @@ public class DefaultBeanIntrospection extends 
ServiceSupport implements BeanIntr
 
     @Override
     public Object getProperty(Object target, String propertyName) throws 
NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+        invoked.incrementAndGet();
         return IntrospectionSupport.getProperty(target, propertyName);
     }
 
     @Override
     public Object getOrElseProperty(Object target, String propertyName, Object 
defaultValue) {
+        invoked.incrementAndGet();
         return IntrospectionSupport.getOrElseProperty(target, propertyName, 
defaultValue);
     }
 
     @Override
     public Object getOrElseProperty(Object target, String propertyName, Object 
defaultValue, boolean ignoreCase) {
+        invoked.incrementAndGet();
         return IntrospectionSupport.getOrElseProperty(target, propertyName, 
defaultValue, ignoreCase);
     }
 
     @Override
     public Method getPropertyGetter(Class<?> type, String propertyName) throws 
NoSuchMethodException {
+        invoked.incrementAndGet();
         return IntrospectionSupport.getPropertyGetter(type, propertyName);
     }
 
     @Override
     public Method getPropertyGetter(Class<?> type, String propertyName, 
boolean ignoreCase) throws NoSuchMethodException {
+        invoked.incrementAndGet();
         return IntrospectionSupport.getPropertyGetter(type, propertyName, 
ignoreCase);
     }
 
     @Override
     public Method getPropertySetter(Class<?> type, String propertyName) throws 
NoSuchMethodException {
+        invoked.incrementAndGet();
         return IntrospectionSupport.getPropertySetter(type, propertyName);
     }
 
     @Override
     public boolean isPropertyIsGetter(Class<?> type, String propertyName) {
+        invoked.incrementAndGet();
         return IntrospectionSupport.isPropertyIsGetter(type, propertyName);
     }
 
     @Override
     @Deprecated
     public boolean setProperties(Object target, Map<String, Object> 
properties, String optionPrefix, boolean allowBuilderPattern) throws Exception {
+        invoked.incrementAndGet();
         return IntrospectionSupport.setProperties(target, properties, 
optionPrefix, allowBuilderPattern);
     }
 
     @Override
     @Deprecated
     public boolean setProperties(Object target, Map<String, Object> 
properties, String optionPrefix) throws Exception {
+        invoked.incrementAndGet();
         return IntrospectionSupport.setProperties(target, properties, 
optionPrefix);
     }
 
@@ -143,60 +164,71 @@ public class DefaultBeanIntrospection extends 
ServiceSupport implements BeanIntr
     @Override
     @Deprecated
     public boolean setProperties(CamelContext context, TypeConverter 
typeConverter, Object target, Map<String, Object> properties) throws Exception {
+        invoked.incrementAndGet();
         return IntrospectionSupport.setProperties(context, typeConverter, 
target, properties);
     }
 
     @Override
     @Deprecated
     public boolean setProperties(TypeConverter typeConverter, Object target, 
Map<String, Object> properties) throws Exception {
+        invoked.incrementAndGet();
         return IntrospectionSupport.setProperties(typeConverter, target, 
properties);
     }
 
     @Override
     @Deprecated
     public boolean setProperties(Object target, Map<String, Object> 
properties) throws Exception {
+        invoked.incrementAndGet();
         return IntrospectionSupport.setProperties(target, properties);
     }
 
     @Override
     public boolean setProperty(CamelContext context, TypeConverter 
typeConverter, Object target, String name, Object value, String refName, 
boolean allowBuilderPattern) throws Exception {
+        invoked.incrementAndGet();
         return IntrospectionSupport.setProperty(context, typeConverter, 
target, name, value, refName, allowBuilderPattern);
     }
 
     @Override
     public boolean setProperty(CamelContext context, TypeConverter 
typeConverter, Object target, String name, Object value, String refName, 
boolean allowBuilderPattern, boolean allowPrivateSetter, boolean ignoreCase) 
throws Exception {
+        invoked.incrementAndGet();
         return IntrospectionSupport.setProperty(context, typeConverter, 
target, name, value, refName, allowBuilderPattern, allowPrivateSetter, 
ignoreCase);
     }
 
     @Override
     public boolean setProperty(CamelContext context, Object target, String 
name, Object value) throws Exception {
+        invoked.incrementAndGet();
         return IntrospectionSupport.setProperty(context, target, name, value);
     }
 
     @Override
     public boolean setProperty(CamelContext context, TypeConverter 
typeConverter, Object target, String name, Object value) throws Exception {
+        invoked.incrementAndGet();
         return IntrospectionSupport.setProperty(context, typeConverter, 
target, name, value);
     }
 
     @Override
     public boolean setProperty(TypeConverter typeConverter, Object target, 
String name, Object value) throws Exception {
+        invoked.incrementAndGet();
         return IntrospectionSupport.setProperty(typeConverter, target, name, 
value);
     }
 
     @Override
     @Deprecated
     public boolean setProperty(Object target, String name, Object value, 
boolean allowBuilderPattern) throws Exception {
+        invoked.incrementAndGet();
         return IntrospectionSupport.setProperty(target, name, value, 
allowBuilderPattern);
     }
 
     @Override
     @Deprecated
     public boolean setProperty(Object target, String name, Object value) 
throws Exception {
+        invoked.incrementAndGet();
         return IntrospectionSupport.setProperty(target, name, value);
     }
 
     @Override
     public Set<Method> findSetterMethods(Class<?> clazz, String name, boolean 
allowBuilderPattern, boolean allowPrivateSetter, boolean ignoreCase) {
+        invoked.incrementAndGet();
         return IntrospectionSupport.findSetterMethods(clazz, name, 
allowBuilderPattern, allowPrivateSetter, ignoreCase);
     }
 
@@ -208,5 +240,6 @@ public class DefaultBeanIntrospection extends 
ServiceSupport implements BeanIntr
     @Override
     protected void doStop() throws Exception {
         IntrospectionSupport.stop();
+        LOG.debug("BeanIntrospection invoked: {} times", getInvokedCounter());
     }
 }
diff --git 
a/core/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java 
b/core/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index bb79975..e8ace5f 100644
--- 
a/core/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ 
b/core/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -29,6 +29,7 @@ import org.apache.camel.impl.converter.DefaultTypeConverter;
 import org.apache.camel.impl.engine.BeanProcessorFactoryResolver;
 import org.apache.camel.impl.engine.BeanProxyFactoryResolver;
 import org.apache.camel.impl.engine.DefaultAsyncProcessorAwaitManager;
+import org.apache.camel.impl.engine.DefaultBeanIntrospection;
 import org.apache.camel.impl.engine.DefaultCamelBeanPostProcessor;
 import org.apache.camel.impl.engine.DefaultCamelContextNameStrategy;
 import org.apache.camel.impl.engine.DefaultClassResolver;
@@ -60,6 +61,7 @@ import 
org.apache.camel.impl.health.DefaultHealthCheckRegistry;
 import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
 import org.apache.camel.runtimecatalog.impl.DefaultRuntimeCamelCatalog;
 import org.apache.camel.spi.AsyncProcessorAwaitManager;
+import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.spi.BeanProcessorFactory;
 import org.apache.camel.spi.BeanProxyFactory;
 import org.apache.camel.spi.BeanRepository;
@@ -318,6 +320,11 @@ public class DefaultCamelContext extends 
AbstractModelCamelContext {
     }
 
     @Override
+    protected BeanIntrospection createBeanIntrospection() {
+        return new DefaultBeanIntrospection();
+    }
+
+    @Override
     protected Tracer createTracer() {
         Tracer tracer = null;
         if (getRegistry() != null) {
diff --git 
a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedBeanIntrospectionMBean.java
 
b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedBeanIntrospectionMBean.java
new file mode 100644
index 0000000..487bc3b
--- /dev/null
+++ 
b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedBeanIntrospectionMBean.java
@@ -0,0 +1,26 @@
+/*
+ * 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.api.management.mbean;
+
+import org.apache.camel.api.management.ManagedAttribute;
+
+public interface ManagedBeanIntrospectionMBean extends ManagedServiceMBean {
+
+    @ManagedAttribute(description = "Number of times bean introspection has 
been invoked")
+    long getInvokedCounter();
+
+}
diff --git 
a/core/camel-management-impl/src/main/java/org/apache/camel/management/JmxManagementLifecycleStrategy.java
 
b/core/camel-management-impl/src/main/java/org/apache/camel/management/JmxManagementLifecycleStrategy.java
index 2f4f968..80fa529 100644
--- 
a/core/camel-management-impl/src/main/java/org/apache/camel/management/JmxManagementLifecycleStrategy.java
+++ 
b/core/camel-management-impl/src/main/java/org/apache/camel/management/JmxManagementLifecycleStrategy.java
@@ -53,6 +53,7 @@ import org.apache.camel.cluster.CamelClusterService;
 import org.apache.camel.management.mbean.ManagedAsyncProcessorAwaitManager;
 import org.apache.camel.management.mbean.ManagedBacklogDebugger;
 import org.apache.camel.management.mbean.ManagedBacklogTracer;
+import org.apache.camel.management.mbean.ManagedBeanIntrospection;
 import org.apache.camel.management.mbean.ManagedCamelContext;
 import org.apache.camel.management.mbean.ManagedConsumerCache;
 import org.apache.camel.management.mbean.ManagedEndpoint;
@@ -83,6 +84,7 @@ import org.apache.camel.processor.interceptor.BacklogDebugger;
 import org.apache.camel.processor.interceptor.BacklogTracer;
 import org.apache.camel.runtimecatalog.RuntimeCamelCatalog;
 import org.apache.camel.spi.AsyncProcessorAwaitManager;
+import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.spi.ConsumerCache;
 import org.apache.camel.spi.DataFormat;
 import org.apache.camel.spi.EndpointRegistry;
@@ -524,6 +526,8 @@ public class JmxManagementLifecycleStrategy extends 
ServiceSupport implements Li
             answer = new ManagedProducerCache(context, (ProducerCache) 
service);
         } else if (service instanceof EndpointRegistry) {
             answer = new ManagedEndpointRegistry(context, (EndpointRegistry) 
service);
+        } else if (service instanceof BeanIntrospection) {
+            answer = new ManagedBeanIntrospection(context, (BeanIntrospection) 
service);
         } else if (service instanceof TypeConverterRegistry) {
             answer = new ManagedTypeConverterRegistry(context, 
(TypeConverterRegistry) service);
         } else if (service instanceof RestRegistry) {
diff --git 
a/core/camel-management-impl/src/main/java/org/apache/camel/management/mbean/ManagedBeanIntrospection.java
 
b/core/camel-management-impl/src/main/java/org/apache/camel/management/mbean/ManagedBeanIntrospection.java
new file mode 100644
index 0000000..67faefb
--- /dev/null
+++ 
b/core/camel-management-impl/src/main/java/org/apache/camel/management/mbean/ManagedBeanIntrospection.java
@@ -0,0 +1,45 @@
+/*
+ * 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.management.mbean;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.api.management.ManagedResource;
+import org.apache.camel.api.management.mbean.ManagedBeanIntrospectionMBean;
+import org.apache.camel.spi.BeanIntrospection;
+
+/**
+ *
+ */
+@ManagedResource(description = "Managed BeanIntrospection")
+public class ManagedBeanIntrospection extends ManagedService implements 
ManagedBeanIntrospectionMBean {
+
+    private final BeanIntrospection beanIntrospection;
+
+    public ManagedBeanIntrospection(CamelContext context, BeanIntrospection 
beanIntrospection) {
+        super(context, beanIntrospection);
+        this.beanIntrospection = beanIntrospection;
+    }
+
+    public BeanIntrospection getBeanIntrospection() {
+        return beanIntrospection;
+    }
+
+    @Override
+    public long getInvokedCounter() {
+        return beanIntrospection.getInvokedCounter();
+    }
+}
diff --git a/examples/camel-example-management/pom.xml 
b/examples/camel-example-management/pom.xml
index d867460..f522a88 100644
--- a/examples/camel-example-management/pom.xml
+++ b/examples/camel-example-management/pom.xml
@@ -43,6 +43,11 @@
 
     <dependencies>
 
+        <!-- include JMX management -->
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-management-impl</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-spring</artifactId>

Reply via email to