CAMEL-11455: Fixed camel-mongodb type converters which was implemented wrong and could lead to stop working on first parsing error.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/f85efbd1 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/f85efbd1 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/f85efbd1 Branch: refs/heads/camel-2.19.x Commit: f85efbd1e5fdf80bd3eef0fdc0331301eba435e0 Parents: f4f2a1c Author: Claus Ibsen <davscl...@apache.org> Authored: Sun Jul 23 11:30:06 2017 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Sun Jul 23 13:38:43 2017 +0200 ---------------------------------------------------------------------- .../converters/MongoDbBasicConverters.java | 70 ++--------------- .../converters/MongoDbFallbackConverter.java | 81 ++++++++++++++++++++ .../services/org/apache/camel/TypeConverter | 3 +- .../mongodb/MongoDbExceptionHandlingTest.java | 21 +++++ 4 files changed, 109 insertions(+), 66 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/f85efbd1/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/converters/MongoDbBasicConverters.java ---------------------------------------------------------------------- diff --git a/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/converters/MongoDbBasicConverters.java b/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/converters/MongoDbBasicConverters.java index 9c9c70e..f2332dc 100644 --- a/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/converters/MongoDbBasicConverters.java +++ b/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/converters/MongoDbBasicConverters.java @@ -18,17 +18,12 @@ package org.apache.camel.component.mongodb.converters; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.InputStream; import java.util.Map; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; -import com.mongodb.DBObject; import com.mongodb.util.JSON; import com.mongodb.util.JSONCallback; - import org.apache.camel.Converter; import org.apache.camel.Exchange; import org.apache.camel.converter.IOConverter; @@ -43,9 +38,6 @@ public final class MongoDbBasicConverters { private static final Logger LOG = LoggerFactory.getLogger(MongoDbBasicConverters.class); - // Jackson's ObjectMapper is thread-safe, so no need to create a pool nor synchronize access to it - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - private MongoDbBasicConverters() { } @@ -60,49 +52,13 @@ public final class MongoDbBasicConverters { } @Converter - public static DBObject fromStringToDBObject(String s) { - DBObject answer = null; - try { - answer = (DBObject) JSON.parse(s); - } catch (Exception e) { - LOG.warn("String -> DBObject conversion selected, but the following exception occurred. Returning null.", e); - } - - return answer; - } - - @Converter - public static BasicDBList fromStringToBasicDBList(String s) { - BasicDBList answer = null; - try { - answer = (BasicDBList) JSON.parse(s); - } catch (Exception e) { - LOG.warn("String -> BasicDBList conversion selected, but the following exception occurred. Returning null.", e); - } - - return answer; - } - - @Converter - public static BasicDBObject fromStringToBasicDBObject(String s) { - BasicDBObject answer = null; - try { - answer = (BasicDBObject) JSON.parse(s); - } catch (Exception e) { - LOG.warn("String -> DBObject conversion selected, but the following exception occurred. Returning null.", e); - } - - return answer; - } - - @Converter - public static BasicDBObject fromFileToDBObject(File f, Exchange exchange) throws FileNotFoundException { + public static BasicDBObject fromFileToDBObject(File f, Exchange exchange) throws Exception { return fromInputStreamToDBObject(new FileInputStream(f), exchange); } @Converter - public static BasicDBObject fromInputStreamToDBObject(InputStream is, Exchange exchange) { - BasicDBObject answer = null; + public static BasicDBObject fromInputStreamToDBObject(InputStream is, Exchange exchange) throws Exception { + BasicDBObject answer; try { byte[] input = IOConverter.toBytes(is); @@ -113,16 +69,14 @@ public final class MongoDbBasicConverters { } else { answer = (BasicDBObject) JSON.parse(IOConverter.toString(input, exchange)); } - } catch (Exception e) { - LOG.warn("String -> DBObject conversion selected, but the following exception occurred. Returning null.", e); } finally { // we need to make sure to close the input stream IOHelper.close(is, "InputStream", LOG); } return answer; } - - /** + + /** * If the input starts with any number of whitespace characters and then a '{' character, we * assume it is JSON rather than BSON. There are probably no useful BSON blobs that fit this pattern */ @@ -138,18 +92,4 @@ public final class MongoDbBasicConverters { return true; } - @Converter - public static DBObject fromAnyObjectToDBObject(Object value) { - BasicDBObject answer; - try { - Map<?, ?> m = OBJECT_MAPPER.convertValue(value, Map.class); - answer = new BasicDBObject(m); - } catch (Exception e) { - LOG.warn("Conversion has fallen back to generic Object -> DBObject, but unable to convert type {}. Returning null. {}", - value.getClass().getCanonicalName(), e.getClass().getCanonicalName() + ": " + e.getMessage()); - return null; - } - return answer; - } - } http://git-wip-us.apache.org/repos/asf/camel/blob/f85efbd1/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/converters/MongoDbFallbackConverter.java ---------------------------------------------------------------------- diff --git a/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/converters/MongoDbFallbackConverter.java b/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/converters/MongoDbFallbackConverter.java new file mode 100644 index 0000000..134c2f9 --- /dev/null +++ b/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/converters/MongoDbFallbackConverter.java @@ -0,0 +1,81 @@ +/** + * 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.component.mongodb.converters; + +import java.util.Map; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.mongodb.BasicDBList; +import com.mongodb.BasicDBObject; +import com.mongodb.DBObject; +import com.mongodb.util.JSON; +import org.apache.camel.Converter; +import org.apache.camel.Exchange; +import org.apache.camel.FallbackConverter; +import org.apache.camel.InvalidPayloadException; +import org.apache.camel.spi.TypeConverterRegistry; + +@Converter +public final class MongoDbFallbackConverter { + + // Jackson's ObjectMapper is thread-safe, so no need to create a pool nor synchronize access to it + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + private MongoDbFallbackConverter() { + } + + @FallbackConverter + public static Object convertTo(Class<?> type, Exchange exchange, Object value, TypeConverterRegistry registry) + throws InvalidPayloadException { + + // if the source is a string and we attempt to convert to one of the known mongodb json classes then try that + if (String.class == value.getClass()) { + + if (type == DBObject.class) { + Object out = JSON.parse(value.toString()); + if (out instanceof DBObject) { + return out; + } else { + throw new InvalidPayloadException(exchange, type); + } + } else if (type == BasicDBList.class) { + Object out = JSON.parse(value.toString()); + if (out instanceof BasicDBList) { + return out; + } else { + throw new InvalidPayloadException(exchange, type); + } + } else if (type == BasicDBObject.class) { + Object out = JSON.parse(value.toString()); + if (out instanceof BasicDBObject) { + return out; + } else { + throw new InvalidPayloadException(exchange, type); + } + } + } + + // okay then fallback and use jackson + if (type == DBObject.class) { + Map<?, ?> m = OBJECT_MAPPER.convertValue(value, Map.class); + return new BasicDBObject(m); + } + + return null; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/f85efbd1/components/camel-mongodb/src/main/resources/META-INF/services/org/apache/camel/TypeConverter ---------------------------------------------------------------------- diff --git a/components/camel-mongodb/src/main/resources/META-INF/services/org/apache/camel/TypeConverter b/components/camel-mongodb/src/main/resources/META-INF/services/org/apache/camel/TypeConverter index ca674e5..6119656 100644 --- a/components/camel-mongodb/src/main/resources/META-INF/services/org/apache/camel/TypeConverter +++ b/components/camel-mongodb/src/main/resources/META-INF/services/org/apache/camel/TypeConverter @@ -15,4 +15,5 @@ # limitations under the License. # -org.apache.camel.component.mongodb.converters.MongoDbBasicConverters \ No newline at end of file +org.apache.camel.component.mongodb.converters.MongoDbBasicConverters +org.apache.camel.component.mongodb.converters.MongoDbFallbackConverter \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/f85efbd1/components/camel-mongodb/src/test/java/org/apache/camel/component/mongodb/MongoDbExceptionHandlingTest.java ---------------------------------------------------------------------- diff --git a/components/camel-mongodb/src/test/java/org/apache/camel/component/mongodb/MongoDbExceptionHandlingTest.java b/components/camel-mongodb/src/test/java/org/apache/camel/component/mongodb/MongoDbExceptionHandlingTest.java index dc49466..7cf19a5 100644 --- a/components/camel-mongodb/src/test/java/org/apache/camel/component/mongodb/MongoDbExceptionHandlingTest.java +++ b/components/camel-mongodb/src/test/java/org/apache/camel/component/mongodb/MongoDbExceptionHandlingTest.java @@ -16,6 +16,7 @@ */ package org.apache.camel.component.mongodb; +import com.mongodb.DBObject; import org.apache.camel.builder.RouteBuilder; import org.junit.Test; @@ -38,6 +39,26 @@ public class MongoDbExceptionHandlingTest extends AbstractMongoDbTest { } @Test + public void testInduceParseAndThenOkException() throws Exception { + // Test that the collection has 0 documents in it + assertEquals(0, testCollection.count()); + pumpDataIntoTestCollection(); + + // notice missing quote at the end of Einstein + try { + template.requestBody("direct:findOneByQuery", "{\"scientist\": \"Einstein}"); + fail("Should have thrown an exception"); + } catch (Exception e) { + extractAndAssertCamelMongoDbException(e, null); + } + + // this one is okay + DBObject out = template.requestBody("direct:findOneByQuery", "{\"scientist\": \"Einstein\"}", DBObject.class); + assertNotNull(out); + assertEquals("Einstein", out.get("scientist")); + } + + @Test public void testErroneousDynamicOperation() throws Exception { // Test that the collection has 0 documents in it assertEquals(0, testCollection.count());