Repository: camel
Updated Branches:
  refs/heads/master 735ca601a -> 963506415


CAMEL-7378 Adding outputType to allow user to choose between a List or a 
DBCursor while performing a findAll operation.


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

Branch: refs/heads/master
Commit: 97f4a7cfab29056c5054fc46d6e7fca288e803c1
Parents: 735ca60
Author: Pierre-Alban DEWITTE <padewi...@gmail.com>
Authored: Tue Mar 31 21:25:24 2015 +0200
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Thu Apr 23 13:45:55 2015 +0200

----------------------------------------------------------------------
 .../component/mongodb/MongoDbEndpoint.java      |  38 ++++-
 .../component/mongodb/MongoDbOutputType.java    |  21 +++
 .../component/mongodb/MongoDbProducer.java      |  10 +-
 .../mongodb/MongoDbOutputTypeTest.java          | 139 +++++++++++++++++++
 4 files changed, 202 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/97f4a7cf/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbEndpoint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbEndpoint.java
 
b/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbEndpoint.java
index abe930b..f31faa7 100644
--- 
a/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbEndpoint.java
+++ 
b/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbEndpoint.java
@@ -94,6 +94,9 @@ public class MongoDbEndpoint extends DefaultEndpoint {
     private String tailTrackField;
     private MongoDbTailTrackingConfig tailTrackingConfig;
 
+    @UriParam
+    private MongoDbOutputType outputType;
+
     private DBCollection dbCollection;
     private DB db;
 
@@ -141,6 +144,23 @@ public class MongoDbEndpoint extends DefaultEndpoint {
         return consumer;
     }
 
+    /**
+     * Check if outputType is compatible with operation. DbCursor and 
DBObjectList applies to findAll. DBObject applies to others.
+     */
+    private void validateOutputType(){
+        if(!ObjectHelper.isEmpty(outputType)){
+            if(MongoDbOutputType.DBObjectList.equals(outputType) && 
!(MongoDbOperation.findAll.equals(operation)) ){
+                throw new IllegalArgumentException("outputType DBObjectList is 
only compatible with operation findAll");
+            }
+            if(MongoDbOutputType.DBCursor.equals(outputType) && 
!(MongoDbOperation.findAll.equals(operation)) ){
+                throw new IllegalArgumentException("outputType DBCursor is 
only compatible with operation findAll");
+            }
+            if(MongoDbOutputType.DBObject.equals(outputType) && 
(MongoDbOperation.findAll.equals(operation)) ){
+                throw new IllegalArgumentException("outputType DBObject is not 
compatible with operation findAll");
+            }
+        }
+    }
+
     private void validateOptions(char role) throws IllegalArgumentException {
         // make our best effort to validate, options with defaults are checked 
against their defaults, which is not always a guarantee that
         // they haven't been explicitly set, but it is enough
@@ -151,11 +171,10 @@ public class MongoDbEndpoint extends DefaultEndpoint {
             }
         } else if (role == 'C') {
             if (!ObjectHelper.isEmpty(operation) || 
!ObjectHelper.isEmpty(writeConcern) || writeConcernRef != null
-                   || dynamicity) {
-                throw new IllegalArgumentException("operation, writeConcern, 
writeConcernRef, dynamicity, invokeGetLastError "
+                   || dynamicity || outputType != null) {
+                throw new IllegalArgumentException("operation, writeConcern, 
writeConcernRef, dynamicity, outputType "
                         + "options cannot appear on a consumer endpoint");
             }
-
             if (consumerType == MongoDbConsumerType.tailable) {
                 if (tailTrackIncreasingField == null) {
                     throw new 
IllegalArgumentException("tailTrackIncreasingField option must be set for 
tailable cursor MongoDB consumer endpoint");
@@ -605,4 +624,17 @@ public class MongoDbEndpoint extends DefaultEndpoint {
         this.writeResultAsHeader = writeResultAsHeader;
     }
 
+    public MongoDbOutputType getOutputType() {
+        return outputType;
+    }
+
+    /**
+     * Convert the output of the producer to the selected type : 
"DBObjectList", "DBObject" or "DBCursor".
+     * DBObjectList or DBObject applies to findAll.
+     * DBCursor applies to all other operations.
+     * @param outputType
+     */
+    public void setOutputType(MongoDbOutputType outputType) {
+        this.outputType = outputType;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/97f4a7cf/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbOutputType.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbOutputType.java
 
b/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbOutputType.java
new file mode 100644
index 0000000..5396e85
--- /dev/null
+++ 
b/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbOutputType.java
@@ -0,0 +1,21 @@
+/**
+ * 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;
+
+public enum MongoDbOutputType {
+    DBObjectList, DBObject, DBCursor
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/97f4a7cf/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbProducer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbProducer.java
 
b/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbProducer.java
index 5155161..b6b9939 100644
--- 
a/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbProducer.java
+++ 
b/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbProducer.java
@@ -331,9 +331,13 @@ public class MongoDbProducer extends DefaultProducer {
             }
 
             Message resultMessage = prepareResponseMessage(exchange, 
MongoDbOperation.findAll);
-            resultMessage.setBody(ret.toArray());
-            resultMessage.setHeader(MongoDbConstants.RESULT_TOTAL_SIZE, 
ret.count());
-            resultMessage.setHeader(MongoDbConstants.RESULT_PAGE_SIZE, 
ret.size());
+            if(MongoDbOutputType.DBCursor.equals(endpoint.getOutputType())){
+                resultMessage.setBody(ret.iterator());
+            }else{
+                resultMessage.setBody(ret.toArray());
+                resultMessage.setHeader(MongoDbConstants.RESULT_TOTAL_SIZE, 
ret.count());
+                resultMessage.setHeader(MongoDbConstants.RESULT_PAGE_SIZE, 
ret.size());
+            }
         } finally {
             // make sure the cursor is closed
             if (ret != null) {

http://git-wip-us.apache.org/repos/asf/camel/blob/97f4a7cf/components/camel-mongodb/src/test/java/org/apache/camel/component/mongodb/MongoDbOutputTypeTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-mongodb/src/test/java/org/apache/camel/component/mongodb/MongoDbOutputTypeTest.java
 
b/components/camel-mongodb/src/test/java/org/apache/camel/component/mongodb/MongoDbOutputTypeTest.java
new file mode 100644
index 0000000..6cd4293
--- /dev/null
+++ 
b/components/camel-mongodb/src/test/java/org/apache/camel/component/mongodb/MongoDbOutputTypeTest.java
@@ -0,0 +1,139 @@
+/**
+ * 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;
+
+import com.mongodb.DBCursor;
+import com.mongodb.DBObject;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MongoDbOutputTypeTest extends AbstractMongoDbTest {
+
+    @Test
+    public void testFindAllDBCursor() {
+        // Test that the collection has 0 documents in it
+        assertEquals(0, testCollection.count());
+        pumpDataIntoTestCollection();
+
+        // Repeat ten times, obtain 10 batches of 100 results each time
+        int numToSkip = 0;
+        final int limit = 100;
+        for (int i = 0; i < 10; i++) {
+            Map<String, Object> headers = new HashMap<String, Object>();
+            headers.put(MongoDbConstants.NUM_TO_SKIP, numToSkip);
+            headers.put(MongoDbConstants.LIMIT, 100);
+            Object result = 
template.requestBodyAndHeaders("direct:findAllDBCursor", (Object) null, 
headers);
+            assertTrue("Result is not of type DBCursor", result instanceof 
DBCursor);
+
+            DBCursor resultCursor = ((DBCursor) result);
+            // Ensure that all returned documents contain all fields
+            while (resultCursor.hasNext()) {
+                DBObject dbObject = resultCursor.next();
+                assertNotNull("DBObject in returned list should contain all 
fields", dbObject.get("_id"));
+                assertNotNull("DBObject in returned list should contain all 
fields", dbObject.get("scientist"));
+                assertNotNull("DBObject in returned list should contain all 
fields", dbObject.get("fixedField"));
+            }
+
+            numToSkip = numToSkip + limit;
+        }
+
+    }
+
+    @Test
+    public void testFindAllDBObjectList() {
+        // Test that the collection has 0 documents in it
+        assertEquals(0, testCollection.count());
+        pumpDataIntoTestCollection();
+        Object result = template.requestBody("direct:findAllDBObjectList", 
(Object) null);
+        assertTrue("Result is not of type List", result instanceof List);
+        @SuppressWarnings("unchecked")
+        List<DBObject> resultList = (List<DBObject>) result;
+
+        assertListSize("Result does not contain 1000 elements", resultList, 
1000);
+
+        // Ensure that all returned documents contain all fields
+        for (DBObject dbObject : resultList) {
+            assertNotNull("DBObject in returned list should contain all 
fields", dbObject.get("_id"));
+            assertNotNull("DBObject in returned list should contain all 
fields", dbObject.get("scientist"));
+            assertNotNull("DBObject in returned list should contain all 
fields", dbObject.get("fixedField"));
+        }
+
+        for (Exchange resultExchange : 
getMockEndpoint("mock:resultFindAll").getReceivedExchanges()) {
+            assertEquals("Result total size header should equal 1000", 1000, 
resultExchange.getIn().getHeader(MongoDbConstants.RESULT_TOTAL_SIZE));
+        }
+    }
+
+    @Test
+    public void testInitFindWithWrongOutputType() {
+        try {
+            RouteBuilder taillableRouteBuilder = new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    
from("mongodb:myDb?database={{mongodb.testDb}}&collection={{mongodb.testCollection}}&operation=findById&dynamicity=true&outputType=DBCursor").to("mock:dummy");
+                }
+            };
+            template.getCamelContext().addRoutes(taillableRouteBuilder);
+            fail("Endpoint should not be initialized with a non compatible 
outputType");
+        } catch (Exception exception) {
+            log.debug("Exception raised during initialization", exception);
+            exception.printStackTrace();
+            assertTrue("Exception is not of type IllegalArgumentException", 
exception instanceof IllegalArgumentException);
+        }
+    }
+
+    @Test
+    public void testInitTailWithWrongOutputType() {
+        try {
+            RouteBuilder taillableRouteBuilder = new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    
from("mongodb:myDb?database={{mongodb.testDb}}&collection={{mongodb.cappedTestCollection}}&tailTrackIncreasingField=increasing&outputType=DBCursor")
+                            .id("tailableCursorConsumer1")
+                            .autoStartup(false)
+                            .to("mock:test");
+                }
+            };
+            template.getCamelContext().addRoutes(taillableRouteBuilder);
+            fail("Endpoint should not be initialized with a non compatible 
outputType");
+        } catch (Exception exception) {
+            log.debug("Exception raised during initialization", exception);
+            exception.printStackTrace();
+            assertTrue("Exception is not of type IllegalArgumentException", 
exception instanceof IllegalArgumentException);
+        }
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+
+                from("direct:findAllDBCursor")
+                        
.to("mongodb:myDb?database={{mongodb.testDb}}&collection={{mongodb.testCollection}}&operation=findAll&dynamicity=true&outputType=DBCursor")
+                        .to("mock:resultFindAllDBCursor");
+                from("direct:findAllDBObjectList")
+                        
.to("mongodb:myDb?database={{mongodb.testDb}}&collection={{mongodb.testCollection}}&operation=findAll&outputType=DBObjectList")
+                        .to("mock:resultFindAllDBObjectList");
+
+            }
+        };
+    }
+}

Reply via email to