From c513e9d879c7422b33553ab1c8173f6b0236a724 Mon Sep 17 00:00:00 2001 From: starnowski <33316705+starnowski@users.noreply.github.com> Date: Sat, 7 Mar 2026 16:57:21 +0100 Subject: [PATCH 1/4] #31 - Added tests for spring web application --- .../jamolingo/demo/DemoController.java | 10 ++++ .../demo/DemoControllerIntegrationTest.java | 49 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/demos/spring-boot-webapp/src/main/java/com/github/starnowski/jamolingo/demo/DemoController.java b/demos/spring-boot-webapp/src/main/java/com/github/starnowski/jamolingo/demo/DemoController.java index 3d7d7b5..433d4b2 100644 --- a/demos/spring-boot-webapp/src/main/java/com/github/starnowski/jamolingo/demo/DemoController.java +++ b/demos/spring-boot-webapp/src/main/java/com/github/starnowski/jamolingo/demo/DemoController.java @@ -6,6 +6,8 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; + +import jakarta.servlet.http.HttpServletRequest; import org.bson.Document; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; @@ -21,6 +23,14 @@ public class DemoController { @Autowired private MongoTemplate mongoTemplate; + @GetMapping("/query-with-dollar-parameters") + public Map queryWithDollarParameterOperators( + HttpServletRequest request) + throws Exception { + ODataQueryService.QueryPlan plan = oDataQueryService.buildQueryPlan(request.getQueryString()); + return executeQueryPlan(plan); + } + @GetMapping("/query") public Map query( @RequestParam(name = "filter", required = false) String filter, diff --git a/demos/spring-boot-webapp/src/test/java/com/github/starnowski/jamolingo/demo/DemoControllerIntegrationTest.java b/demos/spring-boot-webapp/src/test/java/com/github/starnowski/jamolingo/demo/DemoControllerIntegrationTest.java index 6a632e0..ff01ee2 100644 --- a/demos/spring-boot-webapp/src/test/java/com/github/starnowski/jamolingo/demo/DemoControllerIntegrationTest.java +++ b/demos/spring-boot-webapp/src/test/java/com/github/starnowski/jamolingo/demo/DemoControllerIntegrationTest.java @@ -87,6 +87,55 @@ public void shouldReturnCount() throws Exception { .andExpect(jsonPath("$['@odata.count']", is(6))); } + @Test + public void shouldFilterByPlainStringWithDollarParameters() throws Exception { + mockMvc + .perform(get("/query-with-dollar-parameters").queryParam("$filter", "plainString eq 'Poem'")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.value", hasSize(1))) + .andExpect(jsonPath("$.value[0].plainString", is("Poem"))); + } + + @Test + public void shouldOrderAndLimitWithDollarParameters() throws Exception { + mockMvc + .perform(get("/query-with-dollar-parameters").queryParam("$orderby", "plainString desc").queryParam("$top", "2")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.value", hasSize(2))) + .andExpect(jsonPath("$.value[0].plainString", is("example2"))) + .andExpect(jsonPath("$.value[1].plainString", is("example1"))); + } + + @Test + public void shouldSkipAndLimitWithDollarParameters() throws Exception { + // sorted desc: example2, example1, eOMtThyhVNLWUZNRcBaQKxI, Some text, Poem, Oleksa, Mario + mockMvc + .perform( + get("/query-with-dollar-parameters").queryParam("$orderby", "plainString desc").queryParam("$skip", "3").queryParam("$top", "1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.value", hasSize(1))) + .andExpect(jsonPath("$.value[0].plainString", is("Some text"))); + } + + @Test + public void shouldSelectFieldsWithDollarParameters() throws Exception { + mockMvc + .perform( + get("/query-with-dollar-parameters").queryParam("$filter", "plainString eq 'Poem'").queryParam("$select", "plainString")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.value[0].plainString", is("Poem"))) + .andExpect(jsonPath("$.value[0].tags").doesNotExist()); + } + + @Test + public void shouldReturnCountWithDollarParameters() throws Exception { + mockMvc + .perform(get("/query-with-dollar-parameters").queryParam("$filter", "contains(plainString, 'e')").queryParam("$count", "true")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.value", hasSize(6))) + .andExpect(jsonPath("$['@odata.count']", is(6))); + } + @Test public void shouldReturn400WhenNoIndexUsed() throws Exception { mockMvc From 65e19a4cdbdf6dd017c2378341a176d9be75276f Mon Sep 17 00:00:00 2001 From: starnowski <33316705+starnowski@users.noreply.github.com> Date: Sat, 7 Mar 2026 17:13:32 +0100 Subject: [PATCH 2/4] #31 - Added tests for quarkus web application --- demos/quarkus-webapp/pom.xml | 4 ++ .../jamolingo/demo/DemoResource.java | 10 +++ .../demo/DemoResourceIntegrationTest.java | 66 +++++++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/demos/quarkus-webapp/pom.xml b/demos/quarkus-webapp/pom.xml index fd6f699..593ada1 100644 --- a/demos/quarkus-webapp/pom.xml +++ b/demos/quarkus-webapp/pom.xml @@ -40,6 +40,10 @@ io.quarkus quarkus-mongodb-client + + io.quarkus + quarkus-undertow + com.github.starnowski.jamolingo core diff --git a/demos/quarkus-webapp/src/main/java/com/github/starnowski/jamolingo/demo/DemoResource.java b/demos/quarkus-webapp/src/main/java/com/github/starnowski/jamolingo/demo/DemoResource.java index 19d6f83..3716bc4 100644 --- a/demos/quarkus-webapp/src/main/java/com/github/starnowski/jamolingo/demo/DemoResource.java +++ b/demos/quarkus-webapp/src/main/java/com/github/starnowski/jamolingo/demo/DemoResource.java @@ -4,10 +4,12 @@ import com.github.starnowski.jamolingo.perf.ExplainAnalyzeResultFactory; import com.mongodb.client.MongoClient; import jakarta.inject.Inject; +import jakarta.servlet.http.HttpServletRequest; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import java.util.ArrayList; @@ -24,6 +26,14 @@ public class DemoResource { @Inject MongoClient mongoClient; + @GET + @Path("/query-with-dollar-parameters") + public Map queryWithDollarParameterOperators(@Context HttpServletRequest request) + throws Exception { + ODataQueryService.QueryPlan plan = oDataQueryService.buildQueryPlan(request.getQueryString()); + return executeQueryPlan(plan); + } + @GET @Path("/query") public Map query( diff --git a/demos/quarkus-webapp/src/test/java/com/github/starnowski/jamolingo/demo/DemoResourceIntegrationTest.java b/demos/quarkus-webapp/src/test/java/com/github/starnowski/jamolingo/demo/DemoResourceIntegrationTest.java index b975fd3..7502926 100644 --- a/demos/quarkus-webapp/src/test/java/com/github/starnowski/jamolingo/demo/DemoResourceIntegrationTest.java +++ b/demos/quarkus-webapp/src/test/java/com/github/starnowski/jamolingo/demo/DemoResourceIntegrationTest.java @@ -95,6 +95,72 @@ public void shouldReturnCount() { .body("'@odata.count'", is(6)); } + @Test + public void shouldFilterByPlainStringWithDollarParameters() { + given() + .queryParam("$filter", "plainString eq 'Poem'") + .when() + .get("/query-with-dollar-parameters") + .then() + .statusCode(200) + .body("value", hasSize(1)) + .body("value[0].plainString", is("Poem")); + } + + @Test + public void shouldOrderAndLimitWithDollarParameters() { + given() + .queryParam("$orderby", "plainString desc") + .queryParam("$top", "2") + .when() + .get("/query-with-dollar-parameters") + .then() + .statusCode(200) + .body("value", hasSize(2)) + .body("value[0].plainString", is("example2")) + .body("value[1].plainString", is("example1")); + } + + @Test + public void shouldSkipAndLimitWithDollarParameters() { + given() + .queryParam("$orderby", "plainString desc") + .queryParam("$skip", "3") + .queryParam("$top", "1") + .when() + .get("/query-with-dollar-parameters") + .then() + .statusCode(200) + .body("value", hasSize(1)) + .body("value[0].plainString", is("Some text")); + } + + @Test + public void shouldSelectFieldsWithDollarParameters() { + given() + .queryParam("$filter", "plainString eq 'Poem'") + .queryParam("$select", "plainString") + .when() + .get("/query-with-dollar-parameters") + .then() + .statusCode(200) + .body("value[0].plainString", is("Poem")) + .body("value[0].tags", is((Object) null)); + } + + @Test + public void shouldReturnCountWithDollarParameters() { + given() + .queryParam("$filter", "contains(plainString, 'e')") + .queryParam("$count", "true") + .when() + .get("/query-with-dollar-parameters") + .then() + .statusCode(200) + .body("value", hasSize(6)) + .body("'@odata.count'", is(6)); + } + @Test public void shouldReturn400WhenNoIndexUsed() { given() From 17a8ec2259c3b4a0341ee3e9e9ef3463431773eb Mon Sep 17 00:00:00 2001 From: starnowski <33316705+starnowski@users.noreply.github.com> Date: Sat, 7 Mar 2026 17:38:51 +0100 Subject: [PATCH 3/4] #31 - Running spotless plugin --- .../operators/filter/FilterOperatorTest.java | 3 +- .../jamolingo/demo/DemoController.java | 8 +-- .../demo/DemoControllerIntegrationTest.java | 58 +++++++++++-------- 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/compat-driver-5.x/src/test/java/com/github/starnowski/jamolingo/compat/driver/operators/filter/FilterOperatorTest.java b/compat-driver-5.x/src/test/java/com/github/starnowski/jamolingo/compat/driver/operators/filter/FilterOperatorTest.java index db36fe6..8277be4 100644 --- a/compat-driver-5.x/src/test/java/com/github/starnowski/jamolingo/compat/driver/operators/filter/FilterOperatorTest.java +++ b/compat-driver-5.x/src/test/java/com/github/starnowski/jamolingo/compat/driver/operators/filter/FilterOperatorTest.java @@ -249,7 +249,8 @@ private static Stream provideShouldReturnExpectedProjectedDocument() } /** - * String comparison is case-sensitive, case-insensitive comparison can be achieved in combination with tolower or toupper. + * String comparison is case-sensitive, case-insensitive comparison can be achieved in combination + * with tolower or toupper. * https://docs.oasis-open.org/odata/odata/v4.01/os/part2-url-conventions/odata-v4.01-os-part2-url-conventions.html#sec_contains * https://docs.oasis-open.org/odata/odata/v4.01/os/part2-url-conventions/odata-v4.01-os-part2-url-conventions.html#sec_endswith * https://docs.oasis-open.org/odata/odata/v4.01/os/part2-url-conventions/odata-v4.01-os-part2-url-conventions.html#sec_startswith diff --git a/demos/spring-boot-webapp/src/main/java/com/github/starnowski/jamolingo/demo/DemoController.java b/demos/spring-boot-webapp/src/main/java/com/github/starnowski/jamolingo/demo/DemoController.java index 433d4b2..0078200 100644 --- a/demos/spring-boot-webapp/src/main/java/com/github/starnowski/jamolingo/demo/DemoController.java +++ b/demos/spring-boot-webapp/src/main/java/com/github/starnowski/jamolingo/demo/DemoController.java @@ -2,12 +2,11 @@ import com.github.starnowski.jamolingo.perf.ExplainAnalyzeResult; import com.github.starnowski.jamolingo.perf.ExplainAnalyzeResultFactory; +import jakarta.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; - -import jakarta.servlet.http.HttpServletRequest; import org.bson.Document; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; @@ -24,9 +23,8 @@ public class DemoController { @Autowired private MongoTemplate mongoTemplate; @GetMapping("/query-with-dollar-parameters") - public Map queryWithDollarParameterOperators( - HttpServletRequest request) - throws Exception { + public Map queryWithDollarParameterOperators(HttpServletRequest request) + throws Exception { ODataQueryService.QueryPlan plan = oDataQueryService.buildQueryPlan(request.getQueryString()); return executeQueryPlan(plan); } diff --git a/demos/spring-boot-webapp/src/test/java/com/github/starnowski/jamolingo/demo/DemoControllerIntegrationTest.java b/demos/spring-boot-webapp/src/test/java/com/github/starnowski/jamolingo/demo/DemoControllerIntegrationTest.java index ff01ee2..414be90 100644 --- a/demos/spring-boot-webapp/src/test/java/com/github/starnowski/jamolingo/demo/DemoControllerIntegrationTest.java +++ b/demos/spring-boot-webapp/src/test/java/com/github/starnowski/jamolingo/demo/DemoControllerIntegrationTest.java @@ -90,50 +90,62 @@ public void shouldReturnCount() throws Exception { @Test public void shouldFilterByPlainStringWithDollarParameters() throws Exception { mockMvc - .perform(get("/query-with-dollar-parameters").queryParam("$filter", "plainString eq 'Poem'")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.value", hasSize(1))) - .andExpect(jsonPath("$.value[0].plainString", is("Poem"))); + .perform( + get("/query-with-dollar-parameters").queryParam("$filter", "plainString eq 'Poem'")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.value", hasSize(1))) + .andExpect(jsonPath("$.value[0].plainString", is("Poem"))); } @Test public void shouldOrderAndLimitWithDollarParameters() throws Exception { mockMvc - .perform(get("/query-with-dollar-parameters").queryParam("$orderby", "plainString desc").queryParam("$top", "2")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.value", hasSize(2))) - .andExpect(jsonPath("$.value[0].plainString", is("example2"))) - .andExpect(jsonPath("$.value[1].plainString", is("example1"))); + .perform( + get("/query-with-dollar-parameters") + .queryParam("$orderby", "plainString desc") + .queryParam("$top", "2")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.value", hasSize(2))) + .andExpect(jsonPath("$.value[0].plainString", is("example2"))) + .andExpect(jsonPath("$.value[1].plainString", is("example1"))); } @Test public void shouldSkipAndLimitWithDollarParameters() throws Exception { // sorted desc: example2, example1, eOMtThyhVNLWUZNRcBaQKxI, Some text, Poem, Oleksa, Mario mockMvc - .perform( - get("/query-with-dollar-parameters").queryParam("$orderby", "plainString desc").queryParam("$skip", "3").queryParam("$top", "1")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.value", hasSize(1))) - .andExpect(jsonPath("$.value[0].plainString", is("Some text"))); + .perform( + get("/query-with-dollar-parameters") + .queryParam("$orderby", "plainString desc") + .queryParam("$skip", "3") + .queryParam("$top", "1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.value", hasSize(1))) + .andExpect(jsonPath("$.value[0].plainString", is("Some text"))); } @Test public void shouldSelectFieldsWithDollarParameters() throws Exception { mockMvc - .perform( - get("/query-with-dollar-parameters").queryParam("$filter", "plainString eq 'Poem'").queryParam("$select", "plainString")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.value[0].plainString", is("Poem"))) - .andExpect(jsonPath("$.value[0].tags").doesNotExist()); + .perform( + get("/query-with-dollar-parameters") + .queryParam("$filter", "plainString eq 'Poem'") + .queryParam("$select", "plainString")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.value[0].plainString", is("Poem"))) + .andExpect(jsonPath("$.value[0].tags").doesNotExist()); } @Test public void shouldReturnCountWithDollarParameters() throws Exception { mockMvc - .perform(get("/query-with-dollar-parameters").queryParam("$filter", "contains(plainString, 'e')").queryParam("$count", "true")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.value", hasSize(6))) - .andExpect(jsonPath("$['@odata.count']", is(6))); + .perform( + get("/query-with-dollar-parameters") + .queryParam("$filter", "contains(plainString, 'e')") + .queryParam("$count", "true")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.value", hasSize(6))) + .andExpect(jsonPath("$['@odata.count']", is(6))); } @Test From 0481a018c43b4850d0824fd2b17f46128153b65f Mon Sep 17 00:00:00 2001 From: starnowski <33316705+starnowski@users.noreply.github.com> Date: Sat, 7 Mar 2026 17:50:24 +0100 Subject: [PATCH 4/4] #31 - Fixed quarkus-webapp --- demos/quarkus-webapp/pom.xml | 4 ---- .../com/github/starnowski/jamolingo/demo/DemoResource.java | 7 ++++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/demos/quarkus-webapp/pom.xml b/demos/quarkus-webapp/pom.xml index 593ada1..fd6f699 100644 --- a/demos/quarkus-webapp/pom.xml +++ b/demos/quarkus-webapp/pom.xml @@ -40,10 +40,6 @@ io.quarkus quarkus-mongodb-client - - io.quarkus - quarkus-undertow - com.github.starnowski.jamolingo core diff --git a/demos/quarkus-webapp/src/main/java/com/github/starnowski/jamolingo/demo/DemoResource.java b/demos/quarkus-webapp/src/main/java/com/github/starnowski/jamolingo/demo/DemoResource.java index 3716bc4..3205e7b 100644 --- a/demos/quarkus-webapp/src/main/java/com/github/starnowski/jamolingo/demo/DemoResource.java +++ b/demos/quarkus-webapp/src/main/java/com/github/starnowski/jamolingo/demo/DemoResource.java @@ -4,7 +4,6 @@ import com.github.starnowski.jamolingo.perf.ExplainAnalyzeResultFactory; import com.mongodb.client.MongoClient; import jakarta.inject.Inject; -import jakarta.servlet.http.HttpServletRequest; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; @@ -12,6 +11,7 @@ import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.UriInfo; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; @@ -28,9 +28,10 @@ public class DemoResource { @GET @Path("/query-with-dollar-parameters") - public Map queryWithDollarParameterOperators(@Context HttpServletRequest request) + public Map queryWithDollarParameterOperators(@Context UriInfo uriInfo) throws Exception { - ODataQueryService.QueryPlan plan = oDataQueryService.buildQueryPlan(request.getQueryString()); + ODataQueryService.QueryPlan plan = + oDataQueryService.buildQueryPlan(uriInfo.getRequestUri().getQuery()); return executeQueryPlan(plan); }