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>