From 810ff95d70c5e5c75d87a9bd0f6de4f704324ca7 Mon Sep 17 00:00:00 2001 From: tvallin Date: Mon, 11 Dec 2023 09:27:48 +0100 Subject: [PATCH 1/2] Mongo db fix + example tests Signed-off-by: tvallin --- .../dbclient/mongodb/StatementParsers.java | 2 + dependencies/pom.xml | 11 ++ .../common/AbstractPokemonService.java | 3 +- examples/dbclient/mongodb/README.md | 2 +- examples/dbclient/mongodb/pom.xml | 32 +++++ .../dbclient/mongo/MongoDbExampleMain.java | 14 +- .../src/main/resources/application.yaml | 10 +- .../examples/dbclient/mongo/MainIT.java | 136 ++++++++++++++++++ examples/dbclient/pokemons/README.md | 4 +- examples/dbclient/pokemons/pom.xml | 31 ++++ .../examples/dbclient/pokemons/Main.java | 23 +-- .../dbclient/pokemons/PokemonMapper.java | 2 +- .../pokemons/src/main/resources/mongo.yaml | 7 +- ...t.java => AbstractPokemonServiceTest.java} | 62 +++++--- .../pokemons/PokemonServiceMongoIT.java | 69 +++++++++ .../src/test/resources/application-test.yaml | 19 --- 16 files changed, 361 insertions(+), 66 deletions(-) create mode 100644 examples/dbclient/mongodb/src/test/java/io/helidon/examples/dbclient/mongo/MainIT.java rename examples/dbclient/pokemons/src/test/java/io/helidon/examples/dbclient/pokemons/{PokemonServiceTest.java => AbstractPokemonServiceTest.java} (67%) create mode 100644 examples/dbclient/pokemons/src/test/java/io/helidon/examples/dbclient/pokemons/PokemonServiceMongoIT.java delete mode 100644 examples/dbclient/pokemons/src/test/resources/application-test.yaml diff --git a/dbclient/mongodb/src/main/java/io/helidon/dbclient/mongodb/StatementParsers.java b/dbclient/mongodb/src/main/java/io/helidon/dbclient/mongodb/StatementParsers.java index 32a389d7c38..043c3bef086 100644 --- a/dbclient/mongodb/src/main/java/io/helidon/dbclient/mongodb/StatementParsers.java +++ b/dbclient/mongodb/src/main/java/io/helidon/dbclient/mongodb/StatementParsers.java @@ -223,6 +223,8 @@ private static CharClass charClass(char c) { }, // Transitions from STRING state { + //LETTER: regular part of the JSON string, keep processing it + State.STRING, // NUMBER: regular part of the JSON string, keep processing it State.STRING, // QUOTE: end of JSON string processing, go back to STATEMENT state diff --git a/dependencies/pom.xml b/dependencies/pom.xml index e045490d990..8691bce8afd 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -146,6 +146,7 @@ 2.0.9 3.3.4 2.0 + 1.19.3 1.4.2 2.1.4 5.0.SP3 @@ -1265,6 +1266,16 @@ hamcrest-core ${version.lib.hamcrest} + + org.testcontainers + junit-jupiter + ${version.lib.testcontainers} + + + org.testcontainers + mongodb + ${version.lib.testcontainers} + org.apache.activemq activemq-kahadb-store diff --git a/examples/dbclient/common/src/main/java/io/helidon/examples/dbclient/common/AbstractPokemonService.java b/examples/dbclient/common/src/main/java/io/helidon/examples/dbclient/common/AbstractPokemonService.java index eaf36eee554..e25db73468c 100644 --- a/examples/dbclient/common/src/main/java/io/helidon/examples/dbclient/common/AbstractPokemonService.java +++ b/examples/dbclient/common/src/main/java/io/helidon/examples/dbclient/common/AbstractPokemonService.java @@ -134,7 +134,8 @@ private void getPokemon(ServerRequest req, ServerResponse res) { private void listPokemons(ServerRequest req, ServerResponse res) { res.send(dbClient.execute() .namedQuery("select-all") - .map(it -> it.as(JsonObject.class))); + .map(it -> it.as(JsonObject.class)) + .toList()); } /** diff --git a/examples/dbclient/mongodb/README.md b/examples/dbclient/mongodb/README.md index 5c1b78034ba..fc9873b743e 100644 --- a/examples/dbclient/mongodb/README.md +++ b/examples/dbclient/mongodb/README.md @@ -38,7 +38,7 @@ The query operation adds database trace. `curl` commands: - `curl http://localhost:8079/db` - list all Pokemon in the database -- `curl -i -X PUT -d '{"name":"Squirtle","type":"water"}' http://localhost:8079/db` - add a new pokemon +- `curl -i -X PUT -H 'Content-type: application/json' -d '{"name":"Squirtle","type":"water"}' http://localhost:8079/db` - add a new pokemon - `curl http://localhost:8079/db/Squirtle` - get a single pokemon - `curl -i -X DELETE http://localhost:8079/db/Squirtle` - delete a single pokemon - `curl -i -X DELETE http://localhost:8079/db` - delete all pokemon diff --git a/examples/dbclient/mongodb/pom.xml b/examples/dbclient/mongodb/pom.xml index e6721b653f6..2ac01646fd5 100644 --- a/examples/dbclient/mongodb/pom.xml +++ b/examples/dbclient/mongodb/pom.xml @@ -105,6 +105,26 @@ helidon-examples-dbclient-common ${project.version} + + io.helidon.logging + helidon-logging-jul + runtime + + + org.testcontainers + junit-jupiter + test + + + org.testcontainers + mongodb + test + + + io.helidon.webserver.testing.junit5 + helidon-webserver-testing-junit5 + test + @@ -118,6 +138,18 @@ + + org.apache.maven.plugins + maven-failsafe-plugin + + + + integration-test + verify + + + + diff --git a/examples/dbclient/mongodb/src/main/java/io/helidon/examples/dbclient/mongo/MongoDbExampleMain.java b/examples/dbclient/mongodb/src/main/java/io/helidon/examples/dbclient/mongo/MongoDbExampleMain.java index 022dc84bf73..9df1a786700 100644 --- a/examples/dbclient/mongodb/src/main/java/io/helidon/examples/dbclient/mongo/MongoDbExampleMain.java +++ b/examples/dbclient/mongodb/src/main/java/io/helidon/examples/dbclient/mongo/MongoDbExampleMain.java @@ -23,6 +23,7 @@ import io.helidon.dbclient.tracing.DbClientTracing; import io.helidon.logging.common.LogConfig; import io.helidon.webserver.WebServer; +import io.helidon.webserver.WebServerConfig; import io.helidon.webserver.http.HttpRouting; /** @@ -55,17 +56,20 @@ static WebServer startServer() { // load logging configuration LogConfig.configureRuntime(); + WebServer server = setupServer(WebServer.builder()); + + System.out.println("WEB server is up! http://localhost:" + server.port() + "/"); + return server; + } + + static WebServer setupServer(WebServerConfig.Builder builder) { // By default, this will pick up application.yaml from the classpath Config config = Config.create(); - WebServer server = WebServer.builder() - .routing(routing -> routing(routing, config)) + return builder.routing(routing -> routing(routing, config)) .config(config.get("server")) .build() .start(); - - System.out.println("WEB server is up! http://localhost:" + server.port() + "/"); - return server; } /** diff --git a/examples/dbclient/mongodb/src/main/resources/application.yaml b/examples/dbclient/mongodb/src/main/resources/application.yaml index 14356c5e88e..1c4f1698afd 100644 --- a/examples/dbclient/mongodb/src/main/resources/application.yaml +++ b/examples/dbclient/mongodb/src/main/resources/application.yaml @@ -36,11 +36,11 @@ db: "query": { ping: 1 } }' # Insert operation contains collection name, operation type and data to be inserted. - # Name variable is stored as MongoDB primary key attribute _id + # Name variable is stored as MongoDB primary key attribute name insert2: '{ "collection": "pokemons", "value": { - "_id": $name, + "name": $name, "type": $type } }' @@ -51,7 +51,7 @@ db: select-one: '{ "collection": "pokemons", "query": { - "_id": ? + "name": ? } }' delete-all: '{ @@ -61,7 +61,7 @@ db: update: '{ "collection": "pokemons", "query": { - "_id": $name + "name": $name }, "value": { $set: { "type": $type } @@ -70,7 +70,7 @@ db: delete: '{ "collection": "pokemons", "query": { - "_id": ? + "name": ? } }' diff --git a/examples/dbclient/mongodb/src/test/java/io/helidon/examples/dbclient/mongo/MainIT.java b/examples/dbclient/mongodb/src/test/java/io/helidon/examples/dbclient/mongo/MainIT.java new file mode 100644 index 00000000000..a7c7f086711 --- /dev/null +++ b/examples/dbclient/mongodb/src/test/java/io/helidon/examples/dbclient/mongo/MainIT.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed 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 io.helidon.examples.dbclient.mongo; + +import java.util.List; +import java.util.Map; + +import io.helidon.config.Config; +import io.helidon.http.Status; +import io.helidon.http.media.jsonb.JsonbSupport; +import io.helidon.http.media.jsonp.JsonpSupport; +import io.helidon.webclient.api.ClientResponseTyped; +import io.helidon.webclient.api.WebClient; +import io.helidon.webserver.WebServer; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonBuilderFactory; +import jakarta.json.JsonObject; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.MongoDBContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +@Testcontainers(disabledWithoutDocker = true) +public class MainIT { + + @Container + static final MongoDBContainer container = new MongoDBContainer("mongo") + .withExposedPorts(27017); + + private static final JsonBuilderFactory JSON_FACTORY = Json.createBuilderFactory(Map.of()); + + private static WebServer server; + private static WebClient client; + + @BeforeAll + static void beforeAll() { + String url = String.format("mongodb://127.0.0.1:%s/pokemon", container.getMappedPort(27017)); + System.setProperty("db.connection.url", url); + server = MongoDbExampleMain.setupServer(WebServer.builder()); + client = WebClient.create(config -> config.baseUri("http://localhost:" + server.port()) + .addMediaSupport(JsonbSupport.create(Config.create())) + .addMediaSupport(JsonpSupport.create())); + } + + @AfterAll + static void afterAll() { + if (server != null && server.isRunning()) { + server.stop(); + } + } + + @Test + void testListAndDeleteAllPokemons() { + List names = listAllPokemons(); + assertThat(names.isEmpty(), is(true)); + + String endpoint = String.format("/db/%s/type/%s", "Raticate", 1); + ClientResponseTyped response = client.post(endpoint).request(String.class); + assertThat(response.status(), is(Status.OK_200)); + + names = listAllPokemons(); + assertThat(names.size(), is(1)); + assertThat(names.getFirst(), is("Raticate")); + + response = client.delete("/db").request(String.class); + assertThat(response.status(), is(Status.OK_200)); + + names = listAllPokemons(); + assertThat(names.isEmpty(), is(true)); + } + + @Test + void testAddUpdateDeletePokemon() { + ClientResponseTyped response; + ClientResponseTyped jsonResponse; + JsonObject pokemon = JSON_FACTORY.createObjectBuilder() + .add("type", 1) + .add("name", "Raticate") + .build(); + + // Add new pokemon + response = client.put("/db").submit(pokemon, String.class); + assertThat(response.entity(), is("Inserted: 1 values")); + + // Get the new pokemon added + jsonResponse = client.get("/db/Raticate").request(JsonObject.class); + assertThat(jsonResponse.status(), is(Status.OK_200)); + assertThat(jsonResponse.entity().getString("name"), is("Raticate")); + assertThat(jsonResponse.entity().getString("type"), is("1")); + + // Update pokemon + response = client.put("/db/Raticate/type/2").request(String.class); + assertThat(response.status(), is(Status.OK_200)); + + // Verify updated pokemon + jsonResponse = client.get("/db/Raticate").request(JsonObject.class); + assertThat(jsonResponse.status(), is(Status.OK_200)); + assertThat(jsonResponse.entity().getString("name"), is("Raticate")); + assertThat(jsonResponse.entity().getString("type"), is("2")); + + // Delete Pokemon + response = client.delete("/db/Raticate").request(String.class); + assertThat(response.status(), is(Status.OK_200)); + + // Verify pokemon is correctly deleted + response = client.get("/db/Raticate").request(String.class); + assertThat(response.status(), is(Status.NOT_FOUND_404)); + } + + private List listAllPokemons() { + ClientResponseTyped response = client.get("/db").request(JsonArray.class); + assertThat(response.status(), is(Status.OK_200)); + return response.entity().stream().map(e -> e.asJsonObject().getString("name")).toList(); + } +} diff --git a/examples/dbclient/pokemons/README.md b/examples/dbclient/pokemons/README.md index 1e6fa18ab06..a2ebdf2a817 100644 --- a/examples/dbclient/pokemons/README.md +++ b/examples/dbclient/pokemons/README.md @@ -120,10 +120,10 @@ curl http://localhost:8080/db/pokemon/2 curl http://localhost:8080/db/pokemon/name/Squirtle # Add a new Pokémon Rattata -curl -i -X POST -d '{"id":7,"name":"Rattata","idType":1}' http://localhost:8080/db/pokemon +curl -i -X POST -H 'Content-type: application/json' -d '{"id":7,"name":"Rattata","idType":1}' http://localhost:8080/db/pokemon # Rename Pokémon with id 7 to Raticate -curl -i -X PUT -d '{"id":7,"name":"Raticate","idType":2}' http://localhost:8080/db/pokemon +curl -i -X PUT -H 'Content-type: application/json' -d '{"id":7,"name":"Raticate","idType":2}' http://localhost:8080/db/pokemon # Delete Pokémon with id 7 curl -i -X DELETE http://localhost:8080/db/pokemon/7 diff --git a/examples/dbclient/pokemons/pom.xml b/examples/dbclient/pokemons/pom.xml index f067b9607ab..2e139dfbc93 100644 --- a/examples/dbclient/pokemons/pom.xml +++ b/examples/dbclient/pokemons/pom.xml @@ -120,11 +120,30 @@ io.helidon.http.media helidon-http-media-jsonb + + org.mongodb + mongodb-driver-sync + io.helidon.logging helidon-logging-jul runtime + + org.mongodb + mongodb-driver-sync + test + + + org.testcontainers + junit-jupiter + test + + + org.testcontainers + mongodb + test + io.helidon.webclient helidon-webclient @@ -158,6 +177,18 @@ + + org.apache.maven.plugins + maven-failsafe-plugin + + + + integration-test + verify + + + + diff --git a/examples/dbclient/pokemons/src/main/java/io/helidon/examples/dbclient/pokemons/Main.java b/examples/dbclient/pokemons/src/main/java/io/helidon/examples/dbclient/pokemons/Main.java index 6f9b98a8537..d746f9349d2 100644 --- a/examples/dbclient/pokemons/src/main/java/io/helidon/examples/dbclient/pokemons/Main.java +++ b/examples/dbclient/pokemons/src/main/java/io/helidon/examples/dbclient/pokemons/Main.java @@ -23,6 +23,7 @@ import io.helidon.dbclient.health.DbClientHealthCheck; import io.helidon.logging.common.LogConfig; import io.helidon.webserver.WebServer; +import io.helidon.webserver.WebServerConfig; import io.helidon.webserver.http.HttpRouting; import io.helidon.webserver.observe.ObserveFeature; import io.helidon.webserver.observe.health.HealthObserver; @@ -73,6 +74,15 @@ private static void startServer() { Config config = mongo ? Config.create(ConfigSources.classpath(MONGO_CFG)) : Config.create(); Config.global(config); + WebServer server = setupServer(WebServer.builder()) + .start(); + + System.out.println("WEB server is up! http://localhost:" + server.port() + "/"); + } + + static WebServer setupServer(WebServerConfig.Builder builder) { + + Config config = Config.global(); // Client services are added through a service loader - see mongoDB example for explicit services DbClient dbClient = DbClient.create(config.get("db")); Contexts.globalContext().register(dbClient); @@ -80,18 +90,13 @@ private static void startServer() { ObserveFeature observe = ObserveFeature.builder() .config(config.get("server.features.observe")) .addObserver(HealthObserver.builder() - .addCheck(DbClientHealthCheck.create(dbClient, config.get("db.health-check"))) - .build()) + .addCheck(DbClientHealthCheck.create(dbClient, config.get("db.health-check"))) + .build()) .build(); - - WebServer server = WebServer.builder() - .config(config.get("server")) + return builder.config(config.get("server")) .addFeature(observe) .routing(Main::routing) - .build() - .start(); - - System.out.println("WEB server is up! http://localhost:" + server.port() + "/"); + .build(); } /** diff --git a/examples/dbclient/pokemons/src/main/java/io/helidon/examples/dbclient/pokemons/PokemonMapper.java b/examples/dbclient/pokemons/src/main/java/io/helidon/examples/dbclient/pokemons/PokemonMapper.java index e74029630c9..e52dd8e9801 100644 --- a/examples/dbclient/pokemons/src/main/java/io/helidon/examples/dbclient/pokemons/PokemonMapper.java +++ b/examples/dbclient/pokemons/src/main/java/io/helidon/examples/dbclient/pokemons/PokemonMapper.java @@ -25,7 +25,7 @@ import io.helidon.dbclient.DbRow; /** - * Maps database statements to {@link io.helidon.examples.dbclient.common.Pokemon} class. + * Maps database statements to {@link io.helidon.examples.dbclient.pokemons.Pokemon} class. */ public class PokemonMapper implements DbMapper { diff --git a/examples/dbclient/pokemons/src/main/resources/mongo.yaml b/examples/dbclient/pokemons/src/main/resources/mongo.yaml index 7950bef16df..5e46bf7d340 100644 --- a/examples/dbclient/pokemons/src/main/resources/mongo.yaml +++ b/examples/dbclient/pokemons/src/main/resources/mongo.yaml @@ -26,11 +26,14 @@ db: connection: url: "mongodb://127.0.0.1:27017/pokemon" init-schema: false + # Transactions are not supported + init-data: false services: tracing: - enabled: true - metrics: - - type: METER + health-check: + type: "query" + statementName: "health-check" statements: # Health check statement. HealthCheck statement type must be a query. health-check: '{ diff --git a/examples/dbclient/pokemons/src/test/java/io/helidon/examples/dbclient/pokemons/PokemonServiceTest.java b/examples/dbclient/pokemons/src/test/java/io/helidon/examples/dbclient/pokemons/AbstractPokemonServiceTest.java similarity index 67% rename from examples/dbclient/pokemons/src/test/java/io/helidon/examples/dbclient/pokemons/PokemonServiceTest.java rename to examples/dbclient/pokemons/src/test/java/io/helidon/examples/dbclient/pokemons/AbstractPokemonServiceTest.java index 20fe37f8586..939e2915861 100644 --- a/examples/dbclient/pokemons/src/test/java/io/helidon/examples/dbclient/pokemons/PokemonServiceTest.java +++ b/examples/dbclient/pokemons/src/test/java/io/helidon/examples/dbclient/pokemons/AbstractPokemonServiceTest.java @@ -18,47 +18,51 @@ import java.util.List; import java.util.Map; +import io.helidon.config.Config; import io.helidon.http.Status; +import io.helidon.http.media.jsonp.JsonpSupport; import io.helidon.webclient.api.ClientResponseTyped; +import io.helidon.webclient.api.WebClient; import io.helidon.webclient.http1.Http1Client; -import io.helidon.webserver.http.HttpRouting; -import io.helidon.webserver.testing.junit5.ServerTest; -import io.helidon.webserver.testing.junit5.SetUpRoute; +import io.helidon.webserver.WebServer; import jakarta.json.Json; import jakarta.json.JsonArray; import jakarta.json.JsonBuilderFactory; import jakarta.json.JsonObject; import jakarta.json.JsonReader; +import jakarta.json.JsonValue; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -/** - * Tests {@link io.helidon.examples.dbclient.pokemons.PokemonService}. - */ -@ServerTest -class PokemonServiceTest { - +abstract class AbstractPokemonServiceTest { private static final JsonBuilderFactory JSON_FACTORY = Json.createBuilderFactory(Map.of()); - private final Http1Client client; + private static WebServer server; + private static WebClient client; - PokemonServiceTest(Http1Client client) { - this.client = client; + static void beforeAll() { + server = Main.setupServer(WebServer.builder()).start(); + client = WebClient.create(config -> config.baseUri("http://localhost:" + server.port()) + .addMediaSupport(JsonpSupport.create()) + .addMediaSupport(JsonpSupport.create())); } - @SetUpRoute - static void routing(HttpRouting.Builder routing) { - routing.register("/db", new PokemonService()); + static void afterAll() { + if (server != null && server.isRunning()) { + server.stop(); + } } @Test void testListAllPokemons() { ClientResponseTyped response = client.get("/db/pokemon").request(JsonArray.class); assertThat(response.status(), is(Status.OK_200)); - List names = response.entity().stream().map(e -> e.asJsonObject().getString("NAME")).toList(); + List names = response.entity().stream().map(AbstractPokemonServiceTest::mapName).toList(); assertThat(names, is(pokemonNames())); } @@ -66,7 +70,7 @@ void testListAllPokemons() { void testListAllPokemonTypes() { ClientResponseTyped response = client.get("/db/type").request(JsonArray.class); assertThat(response.status(), is(Status.OK_200)); - List names = response.entity().stream().map(e -> e.asJsonObject().getString("NAME")).toList(); + List names = response.entity().stream().map(AbstractPokemonServiceTest::mapName).toList(); assertThat(names, is(pokemonTypes())); } @@ -74,14 +78,14 @@ void testListAllPokemonTypes() { void testGetPokemonById() { ClientResponseTyped response = client.get("/db/pokemon/2").request(JsonObject.class); assertThat(response.status(), is(Status.OK_200)); - assertThat(response.entity().getString("NAME"), is("Charmander")); + assertThat(name(response.entity()), is("Charmander")); } @Test void testGetPokemonByName() { ClientResponseTyped response = client.get("/db/pokemon/name/Squirtle").request(JsonObject.class); assertThat(response.status(), is(Status.OK_200)); - assertThat(response.entity().getInt("ID"), is(3)); + assertThat(id(response.entity()), is(3)); } @Test @@ -118,14 +122,30 @@ void testAddUpdateDeletePokemon() { private static List pokemonNames() { try (JsonReader reader = Json.createReader(PokemonService.class.getResourceAsStream("/pokemons.json"))) { - return reader.readArray().stream().map(e -> e.asJsonObject().getString("name")).toList(); + return reader.readArray().stream().map(AbstractPokemonServiceTest::mapName).toList(); } } private static List pokemonTypes() { try (JsonReader reader = Json.createReader(PokemonService.class.getResourceAsStream("/pokemon-types.json"))) { - return reader.readArray().stream().map(e -> e.asJsonObject().getString("name")).toList(); + return reader.readArray().stream().map(AbstractPokemonServiceTest::mapName).toList(); } } + private static String mapName(JsonValue value) { + return name(value.asJsonObject()); + } + + private static String name(JsonObject json) { + return json.containsKey("name") + ? json.getString("name") + : json.getString("NAME"); + } + + private static int id(JsonObject json) { + return json.containsKey("id") + ? json.getInt("id") + : json.getInt("ID"); + } + } diff --git a/examples/dbclient/pokemons/src/test/java/io/helidon/examples/dbclient/pokemons/PokemonServiceMongoIT.java b/examples/dbclient/pokemons/src/test/java/io/helidon/examples/dbclient/pokemons/PokemonServiceMongoIT.java new file mode 100644 index 00000000000..1877eb54d6e --- /dev/null +++ b/examples/dbclient/pokemons/src/test/java/io/helidon/examples/dbclient/pokemons/PokemonServiceMongoIT.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed 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 io.helidon.examples.dbclient.pokemons; + +import java.util.Map; + +import io.helidon.config.Config; +import io.helidon.config.ConfigSources; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.testcontainers.containers.MongoDBContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@Testcontainers(disabledWithoutDocker = true) +public class PokemonServiceMongoIT extends AbstractPokemonServiceTest { + + @Container + static final MongoDBContainer container = new MongoDBContainer("mongo") + .withExposedPorts(27017); + + @BeforeAll + static void start() { + String url = String.format("mongodb://127.0.0.1:%s/pokemon", container.getMappedPort(27017)); + //init-data is false because transactions are not supported + Config.global(Config.builder().addSource(ConfigSources.create( + Map.of("db.connection.url", url, + "db.init-data", "false"))) + .addSource(ConfigSources.classpath("mongo.yaml")) + .build()); + beforeAll(); + } + + @AfterAll + static void stop() { + afterAll(); + } + + void testListAllPokemons() { + //Skip this test - Transactions are not supported + } + + void testListAllPokemonTypes() { + //Skip this test - Transactions are not supported + } + + void testGetPokemonById() { + //Skip this test - Transactions are not supported + } + + void testGetPokemonByName() { + //Skip this test - Transactions are not supported + } + +} diff --git a/examples/dbclient/pokemons/src/test/resources/application-test.yaml b/examples/dbclient/pokemons/src/test/resources/application-test.yaml deleted file mode 100644 index 94947bcb9fb..00000000000 --- a/examples/dbclient/pokemons/src/test/resources/application-test.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# -# Copyright (c) 2023 Oracle and/or its affiliates. -# -# Licensed 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. -# - -db: - connection: - url: jdbc:h2:mem:test From 8e7e467a4edabc9d263e107613b057268f982133 Mon Sep 17 00:00:00 2001 From: tvallin Date: Mon, 11 Dec 2023 14:42:33 +0100 Subject: [PATCH 2/2] review changes Signed-off-by: tvallin --- .../mongodb/src/main/resources/application.yaml | 10 +++++----- .../io/helidon/examples/dbclient/mongo/MainIT.java | 10 ++++++---- examples/dbclient/pokemons/pom.xml | 5 ----- .../io/helidon/examples/dbclient/pokemons/Main.java | 6 +++--- .../dbclient/pokemons/AbstractPokemonServiceTest.java | 3 +-- 5 files changed, 15 insertions(+), 19 deletions(-) diff --git a/examples/dbclient/mongodb/src/main/resources/application.yaml b/examples/dbclient/mongodb/src/main/resources/application.yaml index 1c4f1698afd..14356c5e88e 100644 --- a/examples/dbclient/mongodb/src/main/resources/application.yaml +++ b/examples/dbclient/mongodb/src/main/resources/application.yaml @@ -36,11 +36,11 @@ db: "query": { ping: 1 } }' # Insert operation contains collection name, operation type and data to be inserted. - # Name variable is stored as MongoDB primary key attribute name + # Name variable is stored as MongoDB primary key attribute _id insert2: '{ "collection": "pokemons", "value": { - "name": $name, + "_id": $name, "type": $type } }' @@ -51,7 +51,7 @@ db: select-one: '{ "collection": "pokemons", "query": { - "name": ? + "_id": ? } }' delete-all: '{ @@ -61,7 +61,7 @@ db: update: '{ "collection": "pokemons", "query": { - "name": $name + "_id": $name }, "value": { $set: { "type": $type } @@ -70,7 +70,7 @@ db: delete: '{ "collection": "pokemons", "query": { - "name": ? + "_id": ? } }' diff --git a/examples/dbclient/mongodb/src/test/java/io/helidon/examples/dbclient/mongo/MainIT.java b/examples/dbclient/mongodb/src/test/java/io/helidon/examples/dbclient/mongo/MainIT.java index a7c7f086711..109c11e9407 100644 --- a/examples/dbclient/mongodb/src/test/java/io/helidon/examples/dbclient/mongo/MainIT.java +++ b/examples/dbclient/mongodb/src/test/java/io/helidon/examples/dbclient/mongo/MainIT.java @@ -49,6 +49,7 @@ public class MainIT { .withExposedPorts(27017); private static final JsonBuilderFactory JSON_FACTORY = Json.createBuilderFactory(Map.of()); + private static final String CONNECTION_URL_KEY = "db.connection.url"; private static WebServer server; private static WebClient client; @@ -56,7 +57,7 @@ public class MainIT { @BeforeAll static void beforeAll() { String url = String.format("mongodb://127.0.0.1:%s/pokemon", container.getMappedPort(27017)); - System.setProperty("db.connection.url", url); + System.setProperty(CONNECTION_URL_KEY, url); server = MongoDbExampleMain.setupServer(WebServer.builder()); client = WebClient.create(config -> config.baseUri("http://localhost:" + server.port()) .addMediaSupport(JsonbSupport.create(Config.create())) @@ -68,6 +69,7 @@ static void afterAll() { if (server != null && server.isRunning()) { server.stop(); } + System.clearProperty(CONNECTION_URL_KEY); } @Test @@ -106,7 +108,7 @@ void testAddUpdateDeletePokemon() { // Get the new pokemon added jsonResponse = client.get("/db/Raticate").request(JsonObject.class); assertThat(jsonResponse.status(), is(Status.OK_200)); - assertThat(jsonResponse.entity().getString("name"), is("Raticate")); + assertThat(jsonResponse.entity().getString("_id"), is("Raticate")); assertThat(jsonResponse.entity().getString("type"), is("1")); // Update pokemon @@ -116,7 +118,7 @@ void testAddUpdateDeletePokemon() { // Verify updated pokemon jsonResponse = client.get("/db/Raticate").request(JsonObject.class); assertThat(jsonResponse.status(), is(Status.OK_200)); - assertThat(jsonResponse.entity().getString("name"), is("Raticate")); + assertThat(jsonResponse.entity().getString("_id"), is("Raticate")); assertThat(jsonResponse.entity().getString("type"), is("2")); // Delete Pokemon @@ -131,6 +133,6 @@ void testAddUpdateDeletePokemon() { private List listAllPokemons() { ClientResponseTyped response = client.get("/db").request(JsonArray.class); assertThat(response.status(), is(Status.OK_200)); - return response.entity().stream().map(e -> e.asJsonObject().getString("name")).toList(); + return response.entity().stream().map(e -> e.asJsonObject().getString("_id")).toList(); } } diff --git a/examples/dbclient/pokemons/pom.xml b/examples/dbclient/pokemons/pom.xml index 2e139dfbc93..b4565de69eb 100644 --- a/examples/dbclient/pokemons/pom.xml +++ b/examples/dbclient/pokemons/pom.xml @@ -129,11 +129,6 @@ helidon-logging-jul runtime - - org.mongodb - mongodb-driver-sync - test - org.testcontainers junit-jupiter diff --git a/examples/dbclient/pokemons/src/main/java/io/helidon/examples/dbclient/pokemons/Main.java b/examples/dbclient/pokemons/src/main/java/io/helidon/examples/dbclient/pokemons/Main.java index d746f9349d2..ce59813e9f5 100644 --- a/examples/dbclient/pokemons/src/main/java/io/helidon/examples/dbclient/pokemons/Main.java +++ b/examples/dbclient/pokemons/src/main/java/io/helidon/examples/dbclient/pokemons/Main.java @@ -74,8 +74,7 @@ private static void startServer() { Config config = mongo ? Config.create(ConfigSources.classpath(MONGO_CFG)) : Config.create(); Config.global(config); - WebServer server = setupServer(WebServer.builder()) - .start(); + WebServer server = setupServer(WebServer.builder()); System.out.println("WEB server is up! http://localhost:" + server.port() + "/"); } @@ -96,7 +95,8 @@ static WebServer setupServer(WebServerConfig.Builder builder) { return builder.config(config.get("server")) .addFeature(observe) .routing(Main::routing) - .build(); + .build() + .start(); } /** diff --git a/examples/dbclient/pokemons/src/test/java/io/helidon/examples/dbclient/pokemons/AbstractPokemonServiceTest.java b/examples/dbclient/pokemons/src/test/java/io/helidon/examples/dbclient/pokemons/AbstractPokemonServiceTest.java index 939e2915861..fb36aa3135a 100644 --- a/examples/dbclient/pokemons/src/test/java/io/helidon/examples/dbclient/pokemons/AbstractPokemonServiceTest.java +++ b/examples/dbclient/pokemons/src/test/java/io/helidon/examples/dbclient/pokemons/AbstractPokemonServiceTest.java @@ -46,9 +46,8 @@ abstract class AbstractPokemonServiceTest { private static WebClient client; static void beforeAll() { - server = Main.setupServer(WebServer.builder()).start(); + server = Main.setupServer(WebServer.builder()); client = WebClient.create(config -> config.baseUri("http://localhost:" + server.port()) - .addMediaSupport(JsonpSupport.create()) .addMediaSupport(JsonpSupport.create())); }