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 2019/08/13 04:24:47 UTC

[camel] branch master updated: CAMEL-13861: Fixes missing logic producing empty messages

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/master by this push:
     new 53f415b  CAMEL-13861: Fixes missing logic producing empty messages
53f415b is described below

commit 53f415b516c42224574cd6dcf0217da057171b4f
Author: phantomjinx <p....@phantomjinx.co.uk>
AuthorDate: Fri Aug 9 10:37:14 2019 +0100

    CAMEL-13861: Fixes missing logic producing empty messages
    
    * Olingo[*]Consumer
     * Tests for null results as well as empty collections. Return 0 accordingly
    
    * Adds and updates tests to assume no empty messages unless the
      consumer.sendEmptyMessageWhenIdle property has been configured
---
 .../camel/component/olingo2/Olingo2Consumer.java   |   3 +-
 .../olingo2/Olingo2ComponentConsumerTest.java      | 111 +++++++++++++++-
 .../camel/component/olingo4/Olingo4Consumer.java   |   3 +-
 .../olingo4/Olingo4ComponentConsumerTest.java      | 144 ++++++++++++++++++++-
 4 files changed, 257 insertions(+), 4 deletions(-)

diff --git a/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Consumer.java b/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Consumer.java
index 333e45e..ac0c5ee 100644
--- a/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Consumer.java
+++ b/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Consumer.java
@@ -94,7 +94,8 @@ public class Olingo2Consumer extends AbstractApiConsumer<Olingo2ApiName, Olingo2
             //
             // Allow consumer idle properties to properly handle an empty polling response
             //
-            if (result[0] instanceof ODataFeed && (((ODataFeed) result[0]).getEntries().isEmpty())) {
+            if ((result[0] == null)
+                || (result[0] instanceof ODataFeed && (((ODataFeed) result[0]).getEntries().isEmpty()))) {
                 return 0;
             } else {
                 int processed = ApiConsumerHelper.getResultsProcessed(this, result[0], isSplitResult());
diff --git a/components/camel-olingo2/camel-olingo2-component/src/test/java/org/apache/camel/component/olingo2/Olingo2ComponentConsumerTest.java b/components/camel-olingo2/camel-olingo2-component/src/test/java/org/apache/camel/component/olingo2/Olingo2ComponentConsumerTest.java
index a3a61c8..0af1b81 100644
--- a/components/camel-olingo2/camel-olingo2-component/src/test/java/org/apache/camel/component/olingo2/Olingo2ComponentConsumerTest.java
+++ b/components/camel-olingo2/camel-olingo2-component/src/test/java/org/apache/camel/component/olingo2/Olingo2ComponentConsumerTest.java
@@ -119,8 +119,67 @@ public class Olingo2ComponentConsumerTest extends AbstractOlingo2TestSupport {
         }
     }
 
+    /**
+     * Read entity set of the People object
+     * and filter already seen items on subsequent exchanges
+     * Use a delay since the mock endpoint does not always get
+     * the correct number of exchanges before being satisfied.
+     *
+     * Note:
+     * - consumer.splitResults is set to false since this ensures the first returned message
+     *   contains all the results.
+     * - consumer.sendEmptyMessageWhenIdle is set to false so only 1 message should
+     *   even be returned.
+     */
+    @Test
+    public void testConsumerReadFilterAlreadySeenNoEmptyMsgs() throws Exception {
+        int expectedMsgCount = 1;
+        MockEndpoint mockEndpoint = getMockEndpoint("mock:consumer-alreadyseen");
+        //
+        // Add 1 to count since we want to wait for full result time
+        // before asserting that only 1 message has been delivered
+        //
+        mockEndpoint.expectedMinimumMessageCount(expectedMsgCount + 1);
+        mockEndpoint.setResultWaitTime(6000L);
+
+        RouteBuilder builder = new RouteBuilder() {
+            public void configure() {
+                from("olingo2://read/Manufacturers?filterAlreadySeen=true&"
+                + "consumer.delay=2&consumer.sendEmptyMessageWhenIdle=false&"
+                + "consumer.splitResult=false")
+                    .to("mock:consumer-alreadyseen");
+            };
+        };
+        addRouteAndStartContext(builder);
+
+        //
+        // Want to wait for entire result time & there should
+        // be exactly 1 exchange transmitted to the endpoint
+        //
+        mockEndpoint.assertIsNotSatisfied();
+
+        // Only 1 exchange so this is good!
+        assertEquals(1, mockEndpoint.getExchanges().size());
+        Object body = mockEndpoint.getExchanges().get(0).getIn().getBody();
+
+        //
+        // Only polled message contains all the entities
+        //
+        assertTrue(body instanceof ODataFeed);
+        ODataFeed set = (ODataFeed) body;
+        assertTrue(set.getEntries().size() > 0);
+    }
+
+    /**
+     * WithPredicate in address
+     * FilterAlreadySeen: true
+     * SplitResults: true
+     * consumer.sendEmptyMessageWhenIdle: true
+     *
+     * @throws Exception
+     */
     @Test
-    public void testConsumerReadFilterAlreadySeenWithPredicateAndSplitResults() throws Exception {
+    public void testConsumerReadFilterAlreadySeenWithPredicate1() throws Exception {
         int expectedMsgCount = 3;
         MockEndpoint mockEndpoint = getMockEndpoint("mock:consumer-splitresult-kp-manufacturer");
         mockEndpoint.expectedMinimumMessageCount(expectedMsgCount);
@@ -160,6 +219,56 @@ public class Olingo2ComponentConsumerTest extends AbstractOlingo2TestSupport {
     }
 
     /**
+     * WithPredicate in address
+     * FilterAlreadySeen: true
+     * SplitResults: true
+     * consumer.sendEmptyMessageWhenIdle: false
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testConsumerReadFilterAlreadySeenWithPredicate2() throws Exception {
+        int expectedMsgCount = 1;
+        MockEndpoint mockEndpoint = getMockEndpoint("mock:consumer-splitresult-kp-manufacturer");
+
+        //
+        // Add 1 to count since we want to wait for full result time
+        // before asserting that only 1 message has been delivered
+        //
+        mockEndpoint.expectedMinimumMessageCount(expectedMsgCount + 1);
+        mockEndpoint.setResultWaitTime(6000L);
+
+        RouteBuilder builder = new RouteBuilder() {
+            public void configure() {
+                from("olingo2://read/Manufacturers('1')?filterAlreadySeen=true&"
+                    + "consumer.delay=2&consumer.sendEmptyMessageWhenIdle=false&"
+                    + "consumer.splitResult=true")
+                    .to("mock:consumer-splitresult-kp-manufacturer");
+            };
+        };
+        addRouteAndStartContext(builder);
+
+        //
+        // Want to wait for entire result time & there should
+        // be exactly 1 exchange transmitted to the endpoint
+        //
+        mockEndpoint.assertIsNotSatisfied();
+
+        // Only 1 exchange so this is good!
+        assertEquals(1, mockEndpoint.getExchanges().size());
+
+        Object body = mockEndpoint.getExchanges().get(0).getIn().getBody();
+        //
+        // Only polled message contains the entity
+        //
+        assertTrue(body instanceof ODataEntry);
+        ODataEntry entry = (ODataEntry) body;
+        Object nameValue = entry.getProperties().get("Name");
+        assertNotNull(nameValue);
+        assertEquals("Star Powered Racing", nameValue.toString());
+    }
+
+    /**
      * Read value of the People object and split the results
      * into individual messages
      */
diff --git a/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Consumer.java b/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Consumer.java
index b147108..778e0cb 100644
--- a/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Consumer.java
+++ b/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Consumer.java
@@ -99,7 +99,8 @@ public class Olingo4Consumer extends AbstractApiConsumer<Olingo4ApiName, Olingo4
             //
             // Allow consumer idle properties to properly handle an empty polling response
             //
-            if (result[0] instanceof ClientEntitySet && (((ClientEntitySet) result[0]).getEntities().isEmpty())) {
+            if ((result[0] == null)
+                || (result[0] instanceof ClientEntitySet && (((ClientEntitySet) result[0]).getEntities().isEmpty()))) {
                 return 0;
             } else {
                 int processed = ApiConsumerHelper.getResultsProcessed(this, result[0], isSplitResult());
diff --git a/components/camel-olingo4/camel-olingo4-component/src/test/java/org/apache/camel/component/olingo4/Olingo4ComponentConsumerTest.java b/components/camel-olingo4/camel-olingo4-component/src/test/java/org/apache/camel/component/olingo4/Olingo4ComponentConsumerTest.java
index b288f2b..c81b174 100644
--- a/components/camel-olingo4/camel-olingo4-component/src/test/java/org/apache/camel/component/olingo4/Olingo4ComponentConsumerTest.java
+++ b/components/camel-olingo4/camel-olingo4-component/src/test/java/org/apache/camel/component/olingo4/Olingo4ComponentConsumerTest.java
@@ -47,6 +47,39 @@ public class Olingo4ComponentConsumerTest extends AbstractOlingo4TestSupport {
         startCamelContext();
     }
 
+    @Test
+    public void testConsumerQueryWithExpand() throws Exception {
+        int expectedMsgCount = 1;
+        MockEndpoint mockEndpoint = getMockEndpoint("mock:consumer-query");
+        mockEndpoint.expectedMinimumMessageCount(expectedMsgCount);
+
+        RouteBuilder builder = new RouteBuilder() {
+            public void configure() {
+                from("olingo4://read/" + PEOPLE + "?"
+                        + "$filter=LastName eq 'Whyte'&$expand=Trips")
+                    .to("mock:consumer-query");
+            };
+        };
+        addRouteAndStartContext(builder);
+
+        mockEndpoint.assertIsSatisfied();
+
+        for (int i = 0; i < expectedMsgCount; ++i) {
+            Object body = mockEndpoint.getExchanges().get(i).getIn().getBody();
+
+            if (i == 0) {
+                //
+                // First polled messages contained all the entities
+                //
+                assertTrue(body instanceof ClientEntity);
+                ClientEntity e = (ClientEntity) body;
+                ClientProperty nameProp = e.getProperty("UserName");
+                assertNotNull(nameProp);
+                assertEquals("russellwhyte", nameProp.getValue().toString());
+            }
+        }
+    }
+
     /**
      * Read entity set of the People object
      * and filter already seen items on subsequent exchanges
@@ -96,8 +129,66 @@ public class Olingo4ComponentConsumerTest extends AbstractOlingo4TestSupport {
         }
     }
 
+    /**
+     * Read entity set of the People object
+     * and filter already seen items on subsequent exchanges
+     * Use a delay since the mock endpoint does not always get
+     * the correct number of exchanges before being satisfied.
+     *
+     * Note:
+     * - consumer.splitResults is set to false since this ensures the first returned message
+     *   contains all the results.
+     * - consumer.sendEmptyMessageWhenIdle is set to false so only 1 message should
+     *   even be returned.
+     */
+    @Test
+    public void testConsumerReadFilterAlreadySeenNoEmptyMsgs() throws Exception {
+        int expectedEntities = 20;
+        int expectedMsgCount = 1;
+        MockEndpoint mockEndpoint = getMockEndpoint("mock:consumer-alreadyseen");
+        //
+        // Add 1 to count since we want to wait for full result time
+        // before asserting that only 1 message has been delivered
+        //
+        mockEndpoint.expectedMinimumMessageCount(expectedMsgCount + 1);
+        mockEndpoint.setResultWaitTime(6000L);
+
+        RouteBuilder builder = new RouteBuilder() {
+            public void configure() {
+                from("olingo4://read/" + PEOPLE + "?consumer.delay=2&consumer.sendEmptyMessageWhenIdle=false&consumer.splitResult=false&filterAlreadySeen=true")
+                    .to("mock:consumer-alreadyseen");
+            };
+        };
+        addRouteAndStartContext(builder);
+
+        //
+        // Want to wait for entire result time & there should
+        // be exactly 1 exchange transmitted to the endpoint
+        //
+        mockEndpoint.assertIsNotSatisfied();
+
+        // Only 1 exchange so this is good!
+        assertEquals(1, mockEndpoint.getExchanges().size());
+        Object body = mockEndpoint.getExchanges().get(0).getIn().getBody();
+
+        //
+        // Only polled message contains all the entities
+        //
+        assertTrue(body instanceof ClientEntitySet);
+        ClientEntitySet set = (ClientEntitySet) body;
+        assertEquals(expectedEntities, set.getEntities().size());
+    }
+
+    /**
+     * WithPredicate in address
+     * FilterAlreadySeen: true
+     * SplitResults: true
+     * consumer.sendEmptyMessageWhenIdle: true
+     *
+     * @throws Exception
+     */
     @Test
-    public void testConsumerReadFilterAlreadySeenWithPredicateAndSplitResults() throws Exception {
+    public void testConsumerReadFilterAlreadySeenWithPredicate1() throws Exception {
         int expectedMsgCount = 3;
         MockEndpoint mockEndpoint = getMockEndpoint("mock:consumer-splitresult-kp-airport");
         mockEndpoint.expectedMinimumMessageCount(expectedMsgCount);
@@ -138,6 +229,57 @@ public class Olingo4ComponentConsumerTest extends AbstractOlingo4TestSupport {
     }
 
     /**
+     * WithPredicate in address
+     * FilterAlreadySeen: true
+     * SplitResults: true
+     * consumer.sendEmptyMessageWhenIdle: false
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testConsumerReadFilterAlreadySeenWithPredicate2() throws Exception {
+        int expectedMsgCount = 1;
+        MockEndpoint mockEndpoint = getMockEndpoint("mock:consumer-splitresult-kp-airport");
+
+        //
+        // Add 1 to count since we want to wait for full result time
+        // before asserting that only 1 message has been delivered
+        //
+        mockEndpoint.expectedMinimumMessageCount(expectedMsgCount + 1);
+        mockEndpoint.setResultWaitTime(6000L);
+
+        RouteBuilder builder = new RouteBuilder() {
+            public void configure() {
+                from("olingo4://read/" + AIRPORTS + "('KSFO')"
+                        + "?filterAlreadySeen=true&"
+                        + "consumer.delay=2&consumer.sendEmptyMessageWhenIdle=false&"
+                        + "consumer.splitResult=true")
+                    .to("mock:consumer-splitresult-kp-airport");
+            };
+        };
+        addRouteAndStartContext(builder);
+
+        //
+        // Want to wait for entire result time & there should
+        // be exactly 1 exchange transmitted to the endpoint
+        //
+        mockEndpoint.assertIsNotSatisfied();
+
+        // Only 1 exchange so this is good!
+        assertEquals(1, mockEndpoint.getExchanges().size());
+
+        Object body = mockEndpoint.getExchanges().get(0).getIn().getBody();
+        //
+        // Only polled message contains the entity
+        //
+        assertTrue(body instanceof ClientEntity);
+        ClientEntity ksfoEntity = (ClientEntity) body;
+        ClientProperty nameProp = ksfoEntity.getProperty("Name");
+        assertNotNull(nameProp);
+        assertEquals("San Francisco International Airport", nameProp.getValue().toString());
+    }
+
+    /**
      * Read entity set of the People object and split the results
      * into individual messages
      */