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 2013/08/29 07:20:47 UTC

git commit: CAMEL-6674: Add allowNull option to @Converter for use-cases where a converter may return null as valid response. This fixes some converters for NodeList to Node which didnt work correctly before.

Updated Branches:
  refs/heads/master a59bf6258 -> f2b697b10


CAMEL-6674: Add allowNull option to @Converter for use-cases where a converter may return null as valid response. This fixes some converters for NodeList to Node which didnt work correctly before.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/f2b697b1
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/f2b697b1
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/f2b697b1

Branch: refs/heads/master
Commit: f2b697b100d90f234f68d9da803e4c15b101f080
Parents: a59bf62
Author: Claus Ibsen <da...@apache.org>
Authored: Wed Aug 28 15:31:34 2013 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Wed Aug 28 16:20:03 2013 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/camel/Converter.java   |  5 ++
 .../org/apache/camel/FallbackConverter.java     |  6 ++
 .../java/org/apache/camel/TypeConverter.java    |  7 ++
 .../camel/converter/jaxp/XmlConverter.java      | 37 +++-------
 .../AnnotationTypeConverterLoader.java          | 26 ++++---
 .../converter/BaseTypeConverterRegistry.java    | 11 ++-
 .../impl/converter/DefaultTypeConverter.java    |  5 ++
 .../InstanceMethodFallbackTypeConverter.java    | 12 ++++
 .../converter/InstanceMethodTypeConverter.java  | 12 ++++
 .../converter/LazyLoadingTypeConverter.java     |  5 ++
 .../converter/PropertyEditorTypeConverter.java  |  5 ++
 .../StaticMethodFallbackTypeConverter.java      | 12 ++++
 .../converter/StaticMethodTypeConverter.java    | 12 ++++
 .../camel/support/TypeConverterSupport.java     |  5 ++
 .../camel/converter/jaxp/XmlConverterTest.java  | 67 ++++++++++--------
 .../camel/impl/TypeConverterAllowNullTest.java  | 74 ++++++++++++++++++++
 .../camel/core/osgi/OsgiTypeConverter.java      |  4 ++
 .../converter/dozer/DozerTypeConverter.java     | 40 ++---------
 .../converter/jaxb/FallbackTypeConverter.java   |  4 ++
 .../camel/component/jms/JmsMessageTypeTest.java | 29 ++------
 20 files changed, 254 insertions(+), 124 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/camel-core/src/main/java/org/apache/camel/Converter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/Converter.java b/camel-core/src/main/java/org/apache/camel/Converter.java
index 0a0a1b2..1652e77 100644
--- a/camel-core/src/main/java/org/apache/camel/Converter.java
+++ b/camel-core/src/main/java/org/apache/camel/Converter.java
@@ -34,4 +34,9 @@ import java.lang.annotation.Target;
 @Documented
 @Target({ElementType.TYPE, ElementType.METHOD })
 public @interface Converter {
+
+    /**
+     * Whether or not returning <tt>null</tt> is a valid response.
+     */
+    boolean allowNull() default false;
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/camel-core/src/main/java/org/apache/camel/FallbackConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/FallbackConverter.java b/camel-core/src/main/java/org/apache/camel/FallbackConverter.java
index f920e7a..6ca5256 100644
--- a/camel-core/src/main/java/org/apache/camel/FallbackConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/FallbackConverter.java
@@ -44,7 +44,13 @@ import java.lang.annotation.Target;
 public @interface FallbackConverter {
 
     /**
+     * Whether or not returning <tt>null</tt> is a valid response.
+     */
+    boolean allowNull() default false;
+
+    /**
      * Whether or not this fallback converter can be promoted to a first class type converter.
      */
     boolean canPromote() default false;
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/camel-core/src/main/java/org/apache/camel/TypeConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/TypeConverter.java b/camel-core/src/main/java/org/apache/camel/TypeConverter.java
index f1ef474..08c83f6 100644
--- a/camel-core/src/main/java/org/apache/camel/TypeConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/TypeConverter.java
@@ -28,6 +28,13 @@ package org.apache.camel;
 public interface TypeConverter {
 
     /**
+     * Whether the type converter allows returning null as a valid response.
+     * <p/>
+     * By default <tt>null</tt> is not a valid response, returning <tt>false</tt> from this method.
+     */
+    boolean allowNull();
+
+    /**
      * Converts the value to the specified type
      *
      * @param type the requested type

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java b/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java
index f2ec5a2..994a724 100644
--- a/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java
@@ -136,7 +136,6 @@ public class XmlConverter {
         return new BytesSource(data);
     }
 
-
     /**
      * Converts the given String to a Source
      */
@@ -468,44 +467,29 @@ public class XmlConverter {
 
     @Converter
     public StreamSource toStreamSource(InputStream in) throws TransformerException {
-        if (in != null) {
-            return new StreamSource(in);
-        }
-        return null;
+        return new StreamSource(in);
     }
 
     @Converter
     public StreamSource toStreamSource(Reader in) throws TransformerException {
-        if (in != null) {
-            return new StreamSource(in);
-        }
-        return null;
+        return new StreamSource(in);
     }
 
     @Converter
     public StreamSource toStreamSource(File in) throws TransformerException {
-        if (in != null) {
-            return new StreamSource(in);
-        }
-        return null;
+        return new StreamSource(in);
     }
 
     @Converter
     public StreamSource toStreamSource(byte[] in, Exchange exchange) throws TransformerException {
-        if (in != null) {
-            InputStream is = exchange.getContext().getTypeConverter().convertTo(InputStream.class, exchange, in);
-            return new StreamSource(is);
-        }
-        return null;
+        InputStream is = exchange.getContext().getTypeConverter().convertTo(InputStream.class, exchange, in);
+        return new StreamSource(is);
     }
 
     @Converter
     public StreamSource toStreamSource(ByteBuffer in, Exchange exchange) throws TransformerException {
-        if (in != null) {
-            InputStream is = exchange.getContext().getTypeConverter().convertTo(InputStream.class, exchange, in);
-            return new StreamSource(is);
-        }
-        return null;
+        InputStream is = exchange.getContext().getTypeConverter().convertTo(InputStream.class, exchange, in);
+        return new StreamSource(is);
     }
 
     /**
@@ -631,7 +615,6 @@ public class XmlConverter {
         String str = toString(source, exchange);
         StringReader reader = new StringReader(str);
         return new SAXSource(new InputSource(reader));
-
     }
 
     @Converter
@@ -670,7 +653,7 @@ public class XmlConverter {
      * @param nl the NodeList
      * @return the DOM Node
      */
-    @Converter
+    @Converter(allowNull = true)
     public Node toDOMNodeFromSingleNodeList(NodeList nl) {
         return nl.getLength() == 1 ? nl.item(0) : null;
     }
@@ -681,7 +664,7 @@ public class XmlConverter {
      * @param nl the NodeList
      * @return the DOM Document
      */
-    @Converter
+    @Converter(allowNull = true)
     public Document toDOMDocumentFromSingleNodeList(NodeList nl) throws ParserConfigurationException, TransformerException {
         return nl.getLength() == 1 ? toDOMDocument(nl.item(0)) : null;
     }
@@ -689,7 +672,7 @@ public class XmlConverter {
     /**
      * Converts the given TRaX Source into a W3C DOM node
      */
-    @Converter
+    @Converter(allowNull = true)
     public Node toDOMNode(Source source) throws TransformerException, ParserConfigurationException, IOException, SAXException {
         DOMSource domSrc = toDOMSource(source);
         return domSrc != null ? domSrc.getNode() : null;

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/camel-core/src/main/java/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.java b/camel-core/src/main/java/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.java
index 6508506..5fe4642 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.java
@@ -264,9 +264,17 @@ public class AnnotationTypeConverterLoader implements TypeConverterLoader {
                 // this may be prone to ClassLoader or packaging problems when the same class is defined
                 // in two different jars (as is the case sometimes with specs).
                 if (ObjectHelper.hasAnnotation(method, Converter.class, true)) {
-                    injector = handleHasConverterAnnotation(registry, type, injector, method);
+                    boolean allowNull = false;
+                    if (method.getAnnotation(Converter.class) != null) {
+                        allowNull = method.getAnnotation(Converter.class).allowNull();
+                    }
+                    injector = handleHasConverterAnnotation(registry, type, injector, method, allowNull);
                 } else if (ObjectHelper.hasAnnotation(method, FallbackConverter.class, true)) {
-                    injector = handleHasFallbackConverterAnnotation(registry, type, injector, method);
+                    boolean allowNull = false;
+                    if (method.getAnnotation(FallbackConverter.class) != null) {
+                        allowNull = method.getAnnotation(FallbackConverter.class).allowNull();
+                    }
+                    injector = handleHasFallbackConverterAnnotation(registry, type, injector, method, allowNull);
                 }
             }
 
@@ -279,7 +287,8 @@ public class AnnotationTypeConverterLoader implements TypeConverterLoader {
         }
     }
 
-    private CachingInjector<?> handleHasConverterAnnotation(TypeConverterRegistry registry, Class<?> type, CachingInjector<?> injector, Method method) {
+    private CachingInjector<?> handleHasConverterAnnotation(TypeConverterRegistry registry, Class<?> type,
+                                                            CachingInjector<?> injector, Method method, boolean allowNull) {
         if (isValidConverterMethod(method)) {
             int modifiers = method.getModifiers();
             if (isAbstract(modifiers) || !isPublic(modifiers)) {
@@ -294,13 +303,13 @@ public class AnnotationTypeConverterLoader implements TypeConverterLoader {
                     Class<?> fromType = method.getParameterTypes()[0];
                     if (isStatic(modifiers)) {
                         registerTypeConverter(registry, method, toType, fromType,
-                                new StaticMethodTypeConverter(method));
+                                new StaticMethodTypeConverter(method, allowNull));
                     } else {
                         if (injector == null) {
                             injector = new CachingInjector<Object>(registry, CastUtils.cast(type, Object.class));
                         }
                         registerTypeConverter(registry, method, toType, fromType,
-                                new InstanceMethodTypeConverter(injector, method, registry));
+                                new InstanceMethodTypeConverter(injector, method, registry, allowNull));
                     }
                 }
             }
@@ -311,7 +320,8 @@ public class AnnotationTypeConverterLoader implements TypeConverterLoader {
         return injector;
     }
 
-    private CachingInjector<?> handleHasFallbackConverterAnnotation(TypeConverterRegistry registry, Class<?> type, CachingInjector<?> injector, Method method) {
+    private CachingInjector<?> handleHasFallbackConverterAnnotation(TypeConverterRegistry registry, Class<?> type,
+                                                                    CachingInjector<?> injector, Method method, boolean allowNull) {
         if (isValidFallbackConverterMethod(method)) {
             int modifiers = method.getModifiers();
             if (isAbstract(modifiers) || !isPublic(modifiers)) {
@@ -324,12 +334,12 @@ public class AnnotationTypeConverterLoader implements TypeConverterLoader {
                             + method + " as a fallback converter method returns a void method");
                 } else {
                     if (isStatic(modifiers)) {
-                        registerFallbackTypeConverter(registry, new StaticMethodFallbackTypeConverter(method, registry), method);
+                        registerFallbackTypeConverter(registry, new StaticMethodFallbackTypeConverter(method, registry, allowNull), method);
                     } else {
                         if (injector == null) {
                             injector = new CachingInjector<Object>(registry, CastUtils.cast(type, Object.class));
                         }
-                        registerFallbackTypeConverter(registry, new InstanceMethodFallbackTypeConverter(injector, method, registry), method);
+                        registerFallbackTypeConverter(registry, new InstanceMethodFallbackTypeConverter(injector, method, registry, allowNull), method);
                     }
                 }
             }

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/camel-core/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java b/camel-core/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java
index 7e4fb82..13a78e3 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java
@@ -274,7 +274,9 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
             } else {
                 rc = converter.convertTo(type, exchange, value);
             }
-            if (rc != null) {
+            if (rc == null && converter.allowNull()) {
+                return null;
+            } else if (rc != null) {
                 return rc;
             }
         }
@@ -294,7 +296,9 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
                     } else {
                         rc = tc.convertTo(primitiveType, exchange, value);
                     }
-                    if (rc != null) {
+                    if (rc == null && tc.allowNull()) {
+                        return null;
+                    } else if (rc != null) {
                         return rc;
                     }
                 }
@@ -310,6 +314,9 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
             } else {
                 rc = tc.convertTo(type, exchange, value);
             }
+            if (rc == null && tc.allowNull()) {
+                return null;
+            }
 
             if (Void.TYPE.equals(rc)) {
                 // it cannot be converted so give up

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java b/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java
index 4a013f2..236ad67 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java
@@ -35,6 +35,11 @@ public class DefaultTypeConverter extends BaseTypeConverterRegistry {
     }
 
     @Override
+    public boolean allowNull() {
+        return false;
+    }
+
+    @Override
     protected void doStart() throws Exception {
         super.doStart();
         // load type converters up front

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/camel-core/src/main/java/org/apache/camel/impl/converter/InstanceMethodFallbackTypeConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/InstanceMethodFallbackTypeConverter.java b/camel-core/src/main/java/org/apache/camel/impl/converter/InstanceMethodFallbackTypeConverter.java
index d2abe1b..862e9a6 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/InstanceMethodFallbackTypeConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/converter/InstanceMethodFallbackTypeConverter.java
@@ -35,12 +35,19 @@ public class InstanceMethodFallbackTypeConverter extends TypeConverterSupport {
     private final Method method;
     private final boolean useExchange;
     private final TypeConverterRegistry registry;
+    private final boolean allowNull;
 
+    @Deprecated
     public InstanceMethodFallbackTypeConverter(CachingInjector<?> injector, Method method, TypeConverterRegistry registry) {
+        this(injector, method, registry, false);
+    }
+
+    public InstanceMethodFallbackTypeConverter(CachingInjector<?> injector, Method method, TypeConverterRegistry registry, boolean allowNull) {
         this.injector = injector;
         this.method = method;
         this.useExchange = method.getParameterTypes().length == 4;
         this.registry = registry;
+        this.allowNull = allowNull;
     }
 
     @Override
@@ -48,6 +55,11 @@ public class InstanceMethodFallbackTypeConverter extends TypeConverterSupport {
         return "InstanceMethodFallbackTypeConverter: " + method;
     }
 
+    @Override
+    public boolean allowNull() {
+        return allowNull;
+    }
+
     @SuppressWarnings("unchecked")
     public <T> T convertTo(Class<T> type, Exchange exchange, Object value) {
         Object instance = injector.newInstance();

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/camel-core/src/main/java/org/apache/camel/impl/converter/InstanceMethodTypeConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/InstanceMethodTypeConverter.java b/camel-core/src/main/java/org/apache/camel/impl/converter/InstanceMethodTypeConverter.java
index d487a81..9a41ffc 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/InstanceMethodTypeConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/converter/InstanceMethodTypeConverter.java
@@ -37,12 +37,19 @@ public class InstanceMethodTypeConverter extends TypeConverterSupport {
     private final Method method;
     private final boolean useExchange;
     private final TypeConverterRegistry registry;
+    private final boolean allowNull;
 
+    @Deprecated
     public InstanceMethodTypeConverter(CachingInjector<?> injector, Method method, TypeConverterRegistry registry) {
+        this(injector, method, registry, false);
+    }
+
+    public InstanceMethodTypeConverter(CachingInjector<?> injector, Method method, TypeConverterRegistry registry, boolean allowNull) {
         this.injector = injector;
         this.method = method;
         this.useExchange = method.getParameterTypes().length == 2;
         this.registry = registry;
+        this.allowNull = allowNull;
     }
 
     @Override
@@ -50,6 +57,11 @@ public class InstanceMethodTypeConverter extends TypeConverterSupport {
         return "InstanceMethodTypeConverter: " + method;
     }
 
+    @Override
+    public boolean allowNull() {
+        return allowNull;
+    }
+
     @SuppressWarnings("unchecked")
     public <T> T convertTo(Class<T> type, Exchange exchange, Object value) {
         Object instance = injector.newInstance();

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/camel-core/src/main/java/org/apache/camel/impl/converter/LazyLoadingTypeConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/LazyLoadingTypeConverter.java b/camel-core/src/main/java/org/apache/camel/impl/converter/LazyLoadingTypeConverter.java
index 1b5dafe..1f9326f 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/LazyLoadingTypeConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/converter/LazyLoadingTypeConverter.java
@@ -45,6 +45,11 @@ public class LazyLoadingTypeConverter extends BaseTypeConverterRegistry {
     }
 
     @Override
+    public boolean allowNull() {
+        return false;
+    }
+
+    @Override
     protected Object doConvertTo(final Class<?> type, final Exchange exchange, final Object value, boolean tryConvert) {
         Object answer = super.doConvertTo(type, exchange, value, tryConvert);
         if (answer == null && !loaded.get()) {

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/camel-core/src/main/java/org/apache/camel/impl/converter/PropertyEditorTypeConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/PropertyEditorTypeConverter.java b/camel-core/src/main/java/org/apache/camel/impl/converter/PropertyEditorTypeConverter.java
index 8dbe778..635f734 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/PropertyEditorTypeConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/converter/PropertyEditorTypeConverter.java
@@ -52,6 +52,11 @@ public class PropertyEditorTypeConverter implements TypeConverter {
     }
 
     @Override
+    public boolean allowNull() {
+        return false;
+    }
+
+    @Override
     public <T> T convertTo(Class<T> type, Object value) {
         // We can't convert null values since we can't figure out a property
         // editor for it.

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/camel-core/src/main/java/org/apache/camel/impl/converter/StaticMethodFallbackTypeConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/StaticMethodFallbackTypeConverter.java b/camel-core/src/main/java/org/apache/camel/impl/converter/StaticMethodFallbackTypeConverter.java
index 5d22d98..32709e3 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/StaticMethodFallbackTypeConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/converter/StaticMethodFallbackTypeConverter.java
@@ -33,11 +33,23 @@ public class StaticMethodFallbackTypeConverter extends TypeConverterSupport {
     private final Method method;
     private final boolean useExchange;
     private final TypeConverterRegistry registry;
+    private final boolean allowNull;
 
+    @Deprecated
     public StaticMethodFallbackTypeConverter(Method method, TypeConverterRegistry registry) {
+        this(method, registry, false);
+    }
+
+    public StaticMethodFallbackTypeConverter(Method method, TypeConverterRegistry registry, boolean allowNull) {
         this.method = method;
         this.useExchange = method.getParameterTypes().length == 4;
         this.registry = registry;
+        this.allowNull = allowNull;
+    }
+
+    @Override
+    public boolean allowNull() {
+        return allowNull;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/camel-core/src/main/java/org/apache/camel/impl/converter/StaticMethodTypeConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/StaticMethodTypeConverter.java b/camel-core/src/main/java/org/apache/camel/impl/converter/StaticMethodTypeConverter.java
index f1f6650..d8e0f9b 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/StaticMethodTypeConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/converter/StaticMethodTypeConverter.java
@@ -31,10 +31,17 @@ import org.apache.camel.util.ObjectHelper;
 public class StaticMethodTypeConverter extends TypeConverterSupport {
     private final Method method;
     private final boolean useExchange;
+    private final boolean allowNull;
 
+    @Deprecated
     public StaticMethodTypeConverter(Method method) {
+        this(method,  false);
+    }
+
+    public StaticMethodTypeConverter(Method method, boolean allowNull) {
         this.method = method;
         this.useExchange = method.getParameterTypes().length == 2;
+        this.allowNull = allowNull;
     }
 
     @Override
@@ -42,6 +49,11 @@ public class StaticMethodTypeConverter extends TypeConverterSupport {
         return "StaticMethodTypeConverter: " + method;
     }
 
+    @Override
+    public boolean allowNull() {
+        return allowNull;
+    }
+
     @SuppressWarnings("unchecked")
     public <T> T convertTo(Class<T> type, Exchange exchange, Object value) {
         return useExchange ? (T)ObjectHelper.invokeMethod(method, null, value, exchange)

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/camel-core/src/main/java/org/apache/camel/support/TypeConverterSupport.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/support/TypeConverterSupport.java b/camel-core/src/main/java/org/apache/camel/support/TypeConverterSupport.java
index 970e853..3a9c359 100644
--- a/camel-core/src/main/java/org/apache/camel/support/TypeConverterSupport.java
+++ b/camel-core/src/main/java/org/apache/camel/support/TypeConverterSupport.java
@@ -30,6 +30,11 @@ import org.apache.camel.TypeConverter;
 public abstract class TypeConverterSupport implements TypeConverter {
 
     @Override
+    public boolean allowNull() {
+        return false;
+    }
+
+    @Override
     public <T> T convertTo(Class<T> type, Object value) throws TypeConversionException {
         return convertTo(type, null, value);
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/camel-core/src/test/java/org/apache/camel/converter/jaxp/XmlConverterTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/converter/jaxp/XmlConverterTest.java b/camel-core/src/test/java/org/apache/camel/converter/jaxp/XmlConverterTest.java
index 0e2e622..e1b89af 100644
--- a/camel-core/src/test/java/org/apache/camel/converter/jaxp/XmlConverterTest.java
+++ b/camel-core/src/test/java/org/apache/camel/converter/jaxp/XmlConverterTest.java
@@ -20,7 +20,7 @@ import java.io.File;
 import java.io.InputStream;
 import java.io.Reader;
 import java.nio.ByteBuffer;
-
+import java.util.List;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Source;
 import javax.xml.transform.TransformerException;
@@ -29,17 +29,17 @@ import javax.xml.transform.sax.SAXSource;
 import javax.xml.transform.stax.StAXSource;
 import javax.xml.transform.stream.StreamSource;
 
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.xml.sax.InputSource;
-
 import org.apache.camel.BytesSource;
 import org.apache.camel.CamelContext;
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.Exchange;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.impl.DefaultExchange;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
 
 /**
  * @version 
@@ -347,30 +347,6 @@ public class XmlConverterTest extends ContextTestSupport {
         assertEquals("<foo>bar</foo>", conv.toString(out, null));
     }
 
-    public void testToVariousUsingNull() throws Exception {
-        XmlConverter conv = new XmlConverter();
-
-        InputStream is = null;
-        assertNull(conv.toStreamSource(is));
-
-        Reader reader = null;
-        assertNull(conv.toStreamSource(reader));
-
-        File file = null;
-        assertNull(conv.toStreamSource(file));
-
-        byte[] bytes = null;
-        assertNull(conv.toStreamSource(bytes, null));
-
-        try {
-            Node node = null;
-            conv.toDOMElement(node);
-            fail("Should have thrown exception");
-        } catch (TransformerException e) {
-            // expected
-        }
-    }
-
     public void testToReaderFromSource() throws Exception {
         XmlConverter conv = new XmlConverter();
         SAXSource source = conv.toSAXSource("<foo>bar</foo>", null);
@@ -508,4 +484,35 @@ public class XmlConverterTest extends ContextTestSupport {
         assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><foo>bar</foo>", conv.toString(out, exchange));
     }
 
+    public void testNodeListToNode() throws Exception {
+        Document document = context.getTypeConverter().convertTo(Document.class, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+                + "<foo><hello>Hello World</hello></foo>");
+
+        NodeList nl = document.getElementsByTagName("hello");
+        assertEquals(1, nl.getLength());
+
+        Node node = context.getTypeConverter().convertTo(Node.class, nl);
+        assertNotNull(node);
+
+        document = context.getTypeConverter().convertTo(Document.class, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+                + "<foo><hello>Hello World</hello><hello>Hello Camel</hello></foo>");
+
+        nl = document.getElementsByTagName("hello");
+        assertEquals(2, nl.getLength());
+
+        // not possible as we have 2 elements in the node list
+        node = context.getTypeConverter().convertTo(Node.class, nl);
+        assertNull(node);
+
+        // and we can convert with 1 again
+        document = context.getTypeConverter().convertTo(Document.class, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+                + "<foo><hello>Hello World</hello></foo>");
+
+        nl = document.getElementsByTagName("hello");
+        assertEquals(1, nl.getLength());
+
+        node = context.getTypeConverter().convertTo(Node.class, nl);
+        assertNotNull(node);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/camel-core/src/test/java/org/apache/camel/impl/TypeConverterAllowNullTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/impl/TypeConverterAllowNullTest.java b/camel-core/src/test/java/org/apache/camel/impl/TypeConverterAllowNullTest.java
new file mode 100644
index 0000000..44287e5
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/impl/TypeConverterAllowNullTest.java
@@ -0,0 +1,74 @@
+/**
+ * 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 junit.framework.TestCase;
+import org.apache.camel.Exchange;
+import org.apache.camel.support.TypeConverterSupport;
+
+/**
+ * @version 
+ */
+public class TypeConverterAllowNullTest extends TestCase {
+
+    public void testMissThenAddTypeConverter() {
+        DefaultCamelContext context = new DefaultCamelContext();
+        context.getTypeConverterRegistry().addTypeConverter(MyOrder.class, String.class, new MyOrderTypeConverter());
+
+        MyOrder order = context.getTypeConverter().convertTo(MyOrder.class, "0");
+        assertNull(order);
+
+        // this time it should work
+        order = context.getTypeConverter().convertTo(MyOrder.class, "123");
+        assertNotNull(order);
+        assertEquals(123, order.getId());
+    }
+
+    private static class MyOrder {
+        private int id;
+
+        public int getId() {
+            return id;
+        }
+
+        public void setId(int id) {
+            this.id = id;
+        }
+    }
+
+    private static class MyOrderTypeConverter extends TypeConverterSupport {
+
+        @Override
+        public boolean allowNull() {
+            return true;
+        }
+
+        @SuppressWarnings("unchecked")
+        public <T> T convertTo(Class<T> type, Exchange exchange, Object value) {
+            if ("0".equals(value)) {
+                return null;
+            }
+
+            // converter from value to the MyOrder bean
+            MyOrder order = new MyOrder();
+            order.setId(Integer.parseInt(value.toString()));
+            return (T) order;
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiTypeConverter.java
----------------------------------------------------------------------
diff --git a/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiTypeConverter.java b/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiTypeConverter.java
index aaea468..ba08489 100644
--- a/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiTypeConverter.java
+++ b/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiTypeConverter.java
@@ -95,6 +95,10 @@ public class OsgiTypeConverter extends ServiceSupport implements TypeConverter,
         this.delegate = null;
     }
 
+    public boolean allowNull() {
+        return getDelegate().allowNull();
+    }
+
     public <T> T convertTo(Class<T> type, Object value) {
         return getDelegate().convertTo(type, value);
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/DozerTypeConverter.java
----------------------------------------------------------------------
diff --git a/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/DozerTypeConverter.java b/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/DozerTypeConverter.java
index e5b584c..f1ab849 100644
--- a/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/DozerTypeConverter.java
+++ b/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/DozerTypeConverter.java
@@ -18,8 +18,9 @@ package org.apache.camel.converter.dozer;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
-import org.apache.camel.NoTypeConversionAvailableException;
+import org.apache.camel.TypeConversionException;
 import org.apache.camel.TypeConverter;
+import org.apache.camel.support.TypeConverterSupport;
 import org.dozer.DozerBeanMapper;
 import org.dozer.Mapper;
 
@@ -29,12 +30,11 @@ import org.dozer.Mapper;
  * types. <code>DozerTypeConverter</code>s are created and installed into a
  * {@link CamelContext} by an instance of {@link DozerTypeConverterLoader}.
  * <p>
- * See http://dozer.sourceforge.net} or more information on
- * configuring Dozer
+ * See <a href="http://dozer.sourceforge.net">dozer project page</a> or more information on configuring Dozer
  *
  * @see DozerTypeConverterLoader
  */
-public class DozerTypeConverter implements TypeConverter {
+public class DozerTypeConverter extends TypeConverterSupport {
 
     private final DozerBeanMapper mapper;
 
@@ -46,36 +46,8 @@ public class DozerTypeConverter implements TypeConverter {
         return mapper;
     }
 
-    public <T> T convertTo(Class<T> type, Object value) {
+    @Override
+    public <T> T convertTo(Class<T> type, Exchange exchange, Object value) throws TypeConversionException {
         return mapper.map(value, type);
     }
-
-    public <T> T convertTo(Class<T> type, Exchange exchange, Object value) {
-        return convertTo(type, value);
-    }
-
-    public <T> T mandatoryConvertTo(Class<T> type, Object value) throws NoTypeConversionAvailableException {
-        return convertTo(type, value);
-    }
-
-    public <T> T mandatoryConvertTo(Class<T> type, Exchange exchange, Object value) throws NoTypeConversionAvailableException {
-        return convertTo(type, value);
-    }
-
-    public <T> T tryConvertTo(Class<T> type, Object value) {
-        try {
-            return convertTo(type, value);
-        } catch (Exception e) {
-            return null;
-        }
-    }
-
-    public <T> T tryConvertTo(Class<T> type, Exchange exchange, Object value) {
-        try {
-            return convertTo(type, value);
-        } catch (Exception e) {
-            return null;
-        }
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/FallbackTypeConverter.java
----------------------------------------------------------------------
diff --git a/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/FallbackTypeConverter.java b/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/FallbackTypeConverter.java
index 22c0c50..9b3baac 100644
--- a/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/FallbackTypeConverter.java
+++ b/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/FallbackTypeConverter.java
@@ -71,6 +71,10 @@ public class FallbackTypeConverter extends ServiceSupport implements TypeConvert
         this.prettyPrint = prettyPrint;
     }
 
+    public boolean allowNull() {
+        return false;
+    }
+
     public void setTypeConverter(TypeConverter parentTypeConverter) {
         this.parentTypeConverter = parentTypeConverter;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/f2b697b1/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsMessageTypeTest.java
----------------------------------------------------------------------
diff --git a/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsMessageTypeTest.java b/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsMessageTypeTest.java
index b5dd1c9..bab3190 100644
--- a/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsMessageTypeTest.java
+++ b/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsMessageTypeTest.java
@@ -23,11 +23,13 @@ import javax.jms.ConnectionFactory;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
-import org.apache.camel.TypeConverter;
+import org.apache.camel.TypeConversionException;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.support.TypeConverterSupport;
 import org.apache.camel.test.junit4.CamelTestSupport;
 import org.junit.Test;
+
 import static org.apache.camel.component.jms.JmsComponent.jmsComponentAutoAcknowledge;
 import static org.apache.camel.component.jms.JmsConstants.JMS_MESSAGE_TYPE;
 
@@ -211,7 +213,7 @@ public class JmsMessageTypeTest extends CamelTestSupport {
         };
     }
 
-    public static final class MyFooBean implements TypeConverter, Serializable {
+    public static final class MyFooBean extends TypeConverterSupport implements Serializable {
 
         private static final long serialVersionUID = 1L;
         private String name;
@@ -227,8 +229,9 @@ public class JmsMessageTypeTest extends CamelTestSupport {
             return name;
         }
 
+        @Override
         @SuppressWarnings("unchecked")
-        public <T> T convertTo(Class<T> type, Object value) {
+        public <T> T convertTo(Class<T> type, Exchange exchange, Object value) throws TypeConversionException {
             if (type.isAssignableFrom(String.class)) {
                 return (T) ("Hello " + ((MyFooBean)value).getName());
             }
@@ -242,25 +245,5 @@ public class JmsMessageTypeTest extends CamelTestSupport {
             }
             return null;
         }
-
-        public <T> T convertTo(Class<T> type, Exchange exchange, Object value) {
-            return convertTo(type, value);
-        }
-
-        public <T> T mandatoryConvertTo(Class<T> type, Object value) {
-            return convertTo(type, value);
-        }
-
-        public <T> T mandatoryConvertTo(Class<T> type, Exchange exchange, Object value) {
-            return convertTo(type, value);
-        }
-
-        public <T> T tryConvertTo(Class<T> type, Object value) {
-            return convertTo(type, value);
-        }
-
-        public <T> T tryConvertTo(Class<T> type, Exchange exchange, Object value) {
-            return convertTo(type, value);
-        }
     }
 }