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/jdbc/pom.xml b/examples/dbclient/jdbc/pom.xml
index aeefe4db30c..02a6ef8c9c9 100644
--- a/examples/dbclient/jdbc/pom.xml
+++ b/examples/dbclient/jdbc/pom.xml
@@ -34,6 +34,11 @@
+
+ io.helidon.logging
+ helidon-logging-jul
+ runtime
+
io.helidon.tracing
helidon-tracing
@@ -127,6 +132,31 @@
helidon-metrics-system-meters
runtime
+
+ com.h2database
+ h2
+ test
+
+
+ io.helidon.webclient
+ helidon-webclient
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.hamcrest
+ hamcrest-all
+ test
+
+
+ io.helidon.webserver.testing.junit5
+ helidon-webserver-testing-junit5
+ test
+
diff --git a/examples/dbclient/jdbc/src/main/resources/application.yaml b/examples/dbclient/jdbc/src/main/resources/application.yaml
index f187bc0a8ab..64cbce16324 100644
--- a/examples/dbclient/jdbc/src/main/resources/application.yaml
+++ b/examples/dbclient/jdbc/src/main/resources/application.yaml
@@ -59,7 +59,7 @@ db:
# name prefix defaults to "db.pool." - if you have more than one client within a JVM, you may want to distinguish between them
name-prefix: "hikari."
health-check:
- - type: "query"
+ type: "query"
statementName: "health-check"
services:
tracing:
@@ -68,12 +68,6 @@ db:
# would trace all delete statements
- statement-types: ["DELETE"]
metrics:
- - type: METER
- name-format: "db.meter.overall"
- - type: METER
- # meter per statement name (default name format)
- - type: METER
- name-format: "db.meter.%1$s"
- type: TIMER
errors: false
statement-names: ["select-.*"]
diff --git a/examples/dbclient/jdbc/src/test/java/io/helidon/examples/dbclient/jdbc/MainTest.java b/examples/dbclient/jdbc/src/test/java/io/helidon/examples/dbclient/jdbc/MainTest.java
new file mode 100644
index 00000000000..2cd14d978f5
--- /dev/null
+++ b/examples/dbclient/jdbc/src/test/java/io/helidon/examples/dbclient/jdbc/MainTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.jdbc;
+
+import java.util.List;
+import java.util.Map;
+
+import io.helidon.config.Config;
+import io.helidon.dbclient.DbClient;
+import io.helidon.http.Status;
+import io.helidon.webclient.api.ClientResponseTyped;
+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 jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonBuilderFactory;
+import jakarta.json.JsonObject;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+@ServerTest
+public class MainTest {
+ private static final JsonBuilderFactory JSON_FACTORY = Json.createBuilderFactory(Map.of());
+
+ private final Http1Client client;
+
+ MainTest(Http1Client client) {
+ this.client = client;
+ }
+
+ @SetUpRoute
+ static void routing(HttpRouting.Builder routing) {
+ JdbcExampleMain.routing(routing, DbClient.create(Config.global().get("db")));
+ }
+
+ @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/jdbc/src/test/resources/application-test.yaml b/examples/dbclient/jdbc/src/test/resources/application-test.yaml
new file mode 100644
index 00000000000..94947bcb9fb
--- /dev/null
+++ b/examples/dbclient/jdbc/src/test/resources/application-test.yaml
@@ -0,0 +1,19 @@
+#
+# 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
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