Author: davsclaus Date: Mon Nov 16 16:53:08 2009 New Revision: 880843 URL: http://svn.apache.org/viewvc?rev=880843&view=rev Log: CAMEL-2177: Loading type converters is only done exctly once. Also WARN about overriding type converter fixed when a race condition occured.
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java?rev=880843&r1=880842&r2=880843&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java Mon Nov 16 16:53:08 2009 @@ -671,7 +671,11 @@ public TypeConverter getTypeConverter() { if (typeConverter == null) { - typeConverter = createTypeConverter(); + synchronized (this) { + // we can synchronize on this as there is only one instance + // of the camel context (its the container) + typeConverter = createTypeConverter(); + } } return typeConverter; } Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java?rev=880843&r1=880842&r2=880843&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java Mon Nov 16 16:53:08 2009 @@ -25,6 +25,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicBoolean; import org.apache.camel.CamelExecutionException; import org.apache.camel.Exchange; @@ -41,7 +42,6 @@ import org.apache.commons.logging.LogFactory; import static org.apache.camel.util.ObjectHelper.wrapRuntimeCamelException; - /** * Default implementation of a type converter registry used for * <a href="http://camel.apache.org/type-converter.html">type converters</a> in Camel. @@ -56,7 +56,7 @@ private final List<TypeConverter> fallbackConverters = new ArrayList<TypeConverter>(); private Injector injector; private final FactoryFinder factoryFinder; - private boolean loaded; + private AtomicBoolean loaded = new AtomicBoolean(); public DefaultTypeConverter(PackageScanClassResolver resolver, Injector injector, FactoryFinder factoryFinder) { this.injector = injector; @@ -212,10 +212,14 @@ TypeMapping key = new TypeMapping(toType, fromType); synchronized (typeMappings) { TypeConverter converter = typeMappings.get(key); - if (converter != null) { - LOG.warn("Overriding type converter from: " + converter + " to: " + typeConverter); + // only override it if its different + // as race conditions can lead to many threads trying to promote the same fallback converter + if (typeConverter != converter) { + if (converter != null) { + LOG.warn("Overriding type converter from: " + converter + " to: " + typeConverter); + } + typeMappings.put(key, typeConverter); } - typeMappings.put(key, typeConverter); } } @@ -365,8 +369,11 @@ * Checks if the registry is loaded and if not lazily load it */ protected synchronized void checkLoaded() { - if (!loaded) { - loaded = true; + // must be synchronized to let other threads wait for it to initialize + // also use a atomic boolean so its state is visible for the other threads + // this ensure that at most one thread is loading all the type converters + if (loaded.compareAndSet(false, true)) { + LOG.debug("Loading type converters ..."); try { for (TypeConverterLoader typeConverterLoader : typeConverterLoaders) { typeConverterLoader.load(this); @@ -381,6 +388,7 @@ } catch (Exception e) { throw wrapRuntimeCamelException(e); } + LOG.debug("Loading type converters done"); } }