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.g.richard...@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 */