diff --git a/examples/dbclient/jdbc/src/main/java/io/helidon/examples/dbclient/jdbc/JdbcExampleMain.java b/examples/dbclient/jdbc/src/main/java/io/helidon/examples/dbclient/jdbc/JdbcExampleMain.java index 1f9caabb0..a066d866b 100644 --- a/examples/dbclient/jdbc/src/main/java/io/helidon/examples/dbclient/jdbc/JdbcExampleMain.java +++ b/examples/dbclient/jdbc/src/main/java/io/helidon/examples/dbclient/jdbc/JdbcExampleMain.java @@ -46,12 +46,14 @@ public static void main(String[] args) { LogConfig.configureRuntime(); // Prepare routing for the server - WebServer server = setupServer(WebServer.builder()); + WebServer server = setupServer(WebServer.builder()) + .build() + .start(); System.out.println("WEB server is up! http://localhost:" + server.port() + "/"); } - static WebServer setupServer(WebServerConfig.Builder builder) { + static WebServerConfig.Builder setupServer(WebServerConfig.Builder builder) { // By default, this will pick up application.yaml from the classpath Config config = Config.global(); @@ -68,8 +70,6 @@ static WebServer setupServer(WebServerConfig.Builder builder) { return builder .config(config.get("server")) .addFeature(observe) - .routing(routing -> routing.register("/db", new PokemonService(dbClient))) - .build() - .start(); + .routing(routing -> routing.register("/db", new PokemonService(dbClient))); } } diff --git a/examples/dbclient/jdbc/src/test/java/io/helidon/examples/dbclient/jdbc/AbstractPokemonServiceTest.java b/examples/dbclient/jdbc/src/test/java/io/helidon/examples/dbclient/jdbc/AbstractPokemonServiceTest.java index 384e7daa1..e0eb966df 100644 --- a/examples/dbclient/jdbc/src/test/java/io/helidon/examples/dbclient/jdbc/AbstractPokemonServiceTest.java +++ b/examples/dbclient/jdbc/src/test/java/io/helidon/examples/dbclient/jdbc/AbstractPokemonServiceTest.java @@ -41,7 +41,11 @@ abstract class AbstractPokemonServiceTest { private static WebClient client; static void beforeAll() { - server = JdbcExampleMain.setupServer(WebServer.builder()); + server = JdbcExampleMain.setupServer(WebServer.builder()) + .port(-1) + .build() + .start(); + client = WebClient.create(config -> config.baseUri("http://localhost:" + server.port()) .addMediaSupport(JsonpSupport.create())); } 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 de853eb9c..643204aa7 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 @@ -56,20 +56,20 @@ static WebServer startServer() { // load logging configuration LogConfig.configureRuntime(); - WebServer server = setupServer(WebServer.builder()); + WebServer server = setupServer(WebServer.builder()) + .build() + .start(); System.out.println("WEB server is up! http://localhost:" + server.port() + "/"); return server; } - static WebServer setupServer(WebServerConfig.Builder builder) { + static WebServerConfig.Builder setupServer(WebServerConfig.Builder builder) { // By default, this will pick up application.yaml from the classpath Config config = Config.create(); return builder.routing(routing -> routing(routing, config)) - .config(config.get("server")) - .build() - .start(); + .config(config.get("server")); } /** 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 18b89b947..8f88bef49 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 @@ -58,7 +58,11 @@ public class MainIT { static void beforeAll() { String url = String.format("mongodb://127.0.0.1:%s/pokemon", container.getMappedPort(27017)); System.setProperty(CONNECTION_URL_KEY, url); - server = MongoDbExampleMain.setupServer(WebServer.builder()); + server = MongoDbExampleMain.setupServer(WebServer.builder()) + .port(-1) + .build() + .start(); + client = WebClient.create(config -> config.baseUri("http://localhost:" + server.port()) .addMediaSupport(JsonbSupport.create(Config.create())) .addMediaSupport(JsonpSupport.create())); 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 d3e83ca89..bf56292d7 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,12 +74,14 @@ private static void startServer() { Config config = mongo ? Config.create(ConfigSources.classpath(MONGO_CFG)) : Config.create(); Config.global(config); - WebServer server = setupServer(WebServer.builder()); + WebServer server = setupServer(WebServer.builder()) + .build() + .start(); System.out.println("WEB server is up! http://localhost:" + server.port() + "/"); } - static WebServer setupServer(WebServerConfig.Builder builder) { + static WebServerConfig.Builder setupServer(WebServerConfig.Builder builder) { Config config = Config.global(); // Client services are added through a service loader - see mongoDB example for explicit services @@ -94,9 +96,7 @@ static WebServer setupServer(WebServerConfig.Builder builder) { .build(); return builder.config(config.get("server")) .addFeature(observe) - .routing(Main::routing) - .build() - .start(); + .routing(Main::routing); } /** 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 6f51f44de..80fbba538 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 @@ -42,7 +42,11 @@ abstract class AbstractPokemonServiceTest { private static WebClient client; static void beforeAll() { - server = Main.setupServer(WebServer.builder()); + server = Main.setupServer(WebServer.builder()) + .port(-1) + .build() + .start(); + client = WebClient.create(config -> config.baseUri("http://localhost:" + server.port()) .addMediaSupport(JsonpSupport.create())); } diff --git a/examples/messaging/README.md b/examples/messaging/README.md index 63201c10f..70d3b3dcb 100644 --- a/examples/messaging/README.md +++ b/examples/messaging/README.md @@ -26,16 +26,10 @@ docker run --name='activemq' --rm -p 61616:61616 -p 8161:8161 rmohr/activemq ### Test Oracle database * Start ActiveMQ server locally: ```shell -cd ./docker/oracle-aq-18-xe +cd ./docker/oracle-aq ./buildAndRun.sh ``` -For stopping Oracle database container use: -```shell -cd ./docker/oracle-aq-18-xe -./stopAndClean.sh -``` - ## Helidon SE Reactive Messaging with Kafka Example For demonstration of Helidon SE Messaging with Kafka connector, continue to [Kafka with WebSocket SE Example](kafka-websocket-se/README.md) diff --git a/examples/messaging/docker/oracle-aq-18-xe/buildAndRun.sh b/examples/messaging/docker/oracle-aq-18-xe/buildAndRun.sh deleted file mode 100755 index 6c0095563..000000000 --- a/examples/messaging/docker/oracle-aq-18-xe/buildAndRun.sh +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2020, 2024 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. -# - -CURR_DIR=$(pwd) -TEMP_DIR=../../target -IMAGES_DIR=${TEMP_DIR}/ora-images -COMMIT="a69fe9b08ff147bb746d16af76cc5279ea5baf7a"; -IMAGES_ZIP_URL=https://github.com/oracle/docker-images/archive/${COMMIT:0:7}.zip -IMAGES_ZIP_DIR=docker-images-${COMMIT}/OracleDatabase/SingleInstance/dockerfiles -ORA_DB_VERSION=18.4.0 -BASE_IMAGE_NAME=oracle/database:${ORA_DB_VERSION}-xe -IMAGE_NAME=helidon/oracle-aq-example -CONTAINER_NAME=oracle-aq-example -ORACLE_PWD=frank - -printf "%-100s" "Checking if base image ${BASE_IMAGE_NAME} is available in local repository" -if [[ "$(docker images -q ${BASE_IMAGE_NAME} 2>/dev/null)" == "" ]]; then - printf "NOK\n" - - echo Base image ${BASE_IMAGE_NAME} not found. Building ... - - # cleanup - mkdir -p ${TEMP_DIR} - rm -rf ${IMAGES_DIR} - rm -f ${TEMP_DIR}/ora-images.zip - - # download official oracle docker images - curl -LJ -o ${TEMP_DIR}/ora-images.zip "${IMAGES_ZIP_URL}" - # unzip only image for Oracle database 18.4.0 - unzip -qq ${TEMP_DIR}/ora-images.zip "${IMAGES_ZIP_DIR}/*" -d ${IMAGES_DIR} - mv ${IMAGES_DIR}/${IMAGES_ZIP_DIR}/${ORA_DB_VERSION} ${IMAGES_DIR}/ - mv ${IMAGES_DIR}/${IMAGES_ZIP_DIR}/buildContainerImage.sh ${IMAGES_DIR}/ - - # cleanup - rm -rf ${IMAGES_DIR}/docker-images-${COMMIT} - rm ${TEMP_DIR}/ora-images.zip - - # build base image - # can take long(15 minutes or so) - cd ${IMAGES_DIR} || exit - bash ./buildContainerImage.sh -v ${ORA_DB_VERSION} -x || exit - cd "${CURR_DIR}" || exit -else - printf "OK\n" -fi - -printf "%-100s" "Checking if image ${IMAGE_NAME} is available in local repository" -if [[ "$(docker images -q ${IMAGE_NAME} 2>/dev/null)" == "" ]]; then - printf "NOK\n" - - echo Image ${IMAGE_NAME} not found. Building ... - docker build -t ${IMAGE_NAME} . || exit -else - printf "OK\n" -fi - -printf "%-100s" "Checking if container ${CONTAINER_NAME} is ready" -if [[ $(docker ps -a --filter "name=^/${CONTAINER_NAME}$" --format '{{.Names}}') != "${CONTAINER_NAME}" ]]; then - printf "NOK\n" - - echo "Container ${CONTAINER_NAME} not found. Running ..." - echo "!!! Be aware first time database initialization can take tens of minutes." - echo "!!! Follow docker logs -f ${CONTAINER_NAME} for 'DATABASE IS READY TO USE' message" - - docker run -d --name ${CONTAINER_NAME} \ - -p 1521:1521 \ - -p 5500:5500 \ - -e ORACLE_PWD=${ORACLE_PWD} \ - ${IMAGE_NAME} || exit -else - printf "OK\n" - printf "%-100s" "Checking if container ${CONTAINER_NAME} is started" - if [[ $(docker ps --filter "name=^/${CONTAINER_NAME}$" --format '{{.Names}}') != "${CONTAINER_NAME}" ]]; then - printf "NOK\n" - - echo "Container ${CONTAINER_NAME} not started. Starting ..." - docker start ${CONTAINER_NAME} || exit - else - printf "OK\n" - fi -fi - -echo "Container ${CONTAINER_NAME} with Oracle database ${ORA_DB_VERSION} XE populated with example AQ queues is either started or starting." -echo "For more info about the state of the database investigate logs:" -echo " docker logs -f ${CONTAINER_NAME}" -echo "Url: jdbc:oracle:thin:@localhost:1521:XE" -echo "user: frank" -echo "pass: frank" diff --git a/examples/messaging/docker/oracle-aq-18-xe/Dockerfile b/examples/messaging/docker/oracle-aq/Dockerfile old mode 100644 new mode 100755 similarity index 73% rename from examples/messaging/docker/oracle-aq-18-xe/Dockerfile rename to examples/messaging/docker/oracle-aq/Dockerfile index ed27c31b7..cdffbf88d --- a/examples/messaging/docker/oracle-aq-18-xe/Dockerfile +++ b/examples/messaging/docker/oracle-aq/Dockerfile @@ -13,8 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. # +FROM container-registry.oracle.com/database/express:latest -FROM oracle/database:18.4.0-xe as base - - -COPY init.sql /docker-entrypoint-initdb.d/setup/ \ No newline at end of file +ENV "ORACLE_PWD"="frank" +ENV "ORACLE_ALLOW_REMOTE"="true" +ENV "ORACLE_SID"="XE" +ENV "PORT"="1521" +COPY ["init.sql","/opt/oracle/scripts/startup/"] +EXPOSE 1521 \ No newline at end of file diff --git a/examples/messaging/docker/oracle-aq-18-xe/stopAndClean.sh b/examples/messaging/docker/oracle-aq/buildAndRun.sh similarity index 77% rename from examples/messaging/docker/oracle-aq-18-xe/stopAndClean.sh rename to examples/messaging/docker/oracle-aq/buildAndRun.sh index 4ba522541..47247f52e 100755 --- a/examples/messaging/docker/oracle-aq-18-xe/stopAndClean.sh +++ b/examples/messaging/docker/oracle-aq/buildAndRun.sh @@ -15,6 +15,8 @@ # limitations under the License. # -docker stop oracle-aq-example -docker container rm oracle-aq-example -docker image rm helidon/oracle-aq-example:latest \ No newline at end of file +IMAGE_NAME=helidon/oracle-aq-example +CONTAINER_NAME=oracle-aq-example + +docker build -t ${IMAGE_NAME} . -f Dockerfile +docker run -p 1521:1521 --rm --name ${CONTAINER_NAME} ${IMAGE_NAME} \ No newline at end of file diff --git a/examples/messaging/docker/oracle-aq-18-xe/examples.sql b/examples/messaging/docker/oracle-aq/examples.sql similarity index 100% rename from examples/messaging/docker/oracle-aq-18-xe/examples.sql rename to examples/messaging/docker/oracle-aq/examples.sql diff --git a/examples/messaging/docker/oracle-aq-18-xe/init.sql b/examples/messaging/docker/oracle-aq/init.sql similarity index 100% rename from examples/messaging/docker/oracle-aq-18-xe/init.sql rename to examples/messaging/docker/oracle-aq/init.sql diff --git a/examples/messaging/oracle-aq-websocket-mp/pom.xml b/examples/messaging/oracle-aq-websocket-mp/pom.xml index 4583e6cab..911cf2b1d 100644 --- a/examples/messaging/oracle-aq-websocket-mp/pom.xml +++ b/examples/messaging/oracle-aq-websocket-mp/pom.xml @@ -17,8 +17,8 @@ --> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 io.helidon.applications @@ -34,7 +34,7 @@ io.helidon.microprofile.bundles - helidon-microprofile + helidon-microprofile-core io.helidon.microprofile.messaging @@ -53,12 +53,59 @@ io.helidon.microprofile.websocket helidon-microprofile-websocket + + io.helidon.logging + helidon-logging-jul + + + org.slf4j + slf4j-api + + + org.slf4j + jul-to-slf4j + + + org.slf4j + slf4j-jdk14 + io.smallrye jandex runtime true + + org.testcontainers + junit-jupiter + test + + + org.testcontainers + oracle-xe + test + + + org.junit.jupiter + junit-jupiter-api + test + + + io.helidon.microprofile.testing + helidon-microprofile-testing-junit5 + test + + + io.helidon.messaging.mock + helidon-messaging-mock + test + + + org.mockito + mockito-core + 5.11.0 + test + @@ -72,6 +119,27 @@ + + io.smallrye + jandex-maven-plugin + + + make-index + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + integration-test + verify + + + + diff --git a/examples/messaging/oracle-aq-websocket-mp/src/main/java/io/helidon/examples/messaging/mp/MsgProcessingBean.java b/examples/messaging/oracle-aq-websocket-mp/src/main/java/io/helidon/examples/messaging/mp/MsgProcessingBean.java index ff56228f0..23d14fe4b 100644 --- a/examples/messaging/oracle-aq-websocket-mp/src/main/java/io/helidon/examples/messaging/mp/MsgProcessingBean.java +++ b/examples/messaging/oracle-aq-websocket-mp/src/main/java/io/helidon/examples/messaging/mp/MsgProcessingBean.java @@ -23,19 +23,18 @@ import java.util.concurrent.CompletionStage; import java.util.concurrent.SubmissionPublisher; -import io.helidon.common.reactive.BufferedEmittingPublisher; import io.helidon.common.reactive.Multi; import io.helidon.messaging.connectors.aq.AqMessage; import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import jakarta.jms.JMSException; import jakarta.jms.MapMessage; import org.eclipse.microprofile.reactive.messaging.Acknowledgment; +import org.eclipse.microprofile.reactive.messaging.Channel; +import org.eclipse.microprofile.reactive.messaging.Emitter; import org.eclipse.microprofile.reactive.messaging.Incoming; import org.eclipse.microprofile.reactive.messaging.Outgoing; -import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; -import org.reactivestreams.FlowAdapters; -import org.reactivestreams.Publisher; /** * Bean for message processing. @@ -43,21 +42,11 @@ @ApplicationScoped public class MsgProcessingBean { - private final BufferedEmittingPublisher emitter = BufferedEmittingPublisher.create(); private final SubmissionPublisher broadCaster = new SubmissionPublisher<>(); - /** - * Create a publisher for the emitter. - * - * @return A Publisher from the emitter - */ - @Outgoing("to-queue-1") - public Publisher toFirstQueue() { - // Create new publisher for emitting to by this::process - return ReactiveStreams - .fromPublisher(FlowAdapters.toPublisher(emitter)) - .buildRs(); - } + @Inject + @Channel("to-queue-1") + private Emitter emitter; /** * Example of resending message from one queue to another and logging the payload to DB in the process. @@ -88,11 +77,13 @@ public CompletionStage> betweenQueues(AqMessage msg) { * Broadcasts an event. * * @param msg Message to broadcast + * @return immediately completed future */ @Incoming("from-queue-2") - public void fromSecondQueue(AqMessage msg) { + public CompletionStage fromSecondQueue(AqMessage msg) { // Broadcast to all subscribers broadCaster.submit(msg.getPayload()); + return CompletableFuture.completedFuture(null); } /** @@ -120,10 +111,10 @@ public void fromMapQueue(MapMessage msg) throws JMSException { } Multi subscribeMulti() { - return Multi.create(broadCaster).log(); + return Multi.create(broadCaster); } void process(final String msg) { - emitter.emit(msg); + emitter.send(msg); } } diff --git a/examples/messaging/oracle-aq-websocket-mp/src/main/resources/META-INF/microprofile-config.properties b/examples/messaging/oracle-aq-websocket-mp/src/main/resources/META-INF/microprofile-config.properties deleted file mode 100644 index 79eb7b61d..000000000 --- a/examples/messaging/oracle-aq-websocket-mp/src/main/resources/META-INF/microprofile-config.properties +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright (c) 2020, 2024 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. -# - -server.port=7001 -server.host=0.0.0.0 -server.static.classpath.location=/WEB -server.static.classpath.welcome=index.html - -javax.sql.DataSource.aq-test-ds.connectionFactoryClassName=oracle.jdbc.pool.OracleDataSource -javax.sql.DataSource.aq-test-ds.URL=jdbc:oracle:thin:@localhost:1521:XE -javax.sql.DataSource.aq-test-ds.user=frank -javax.sql.DataSource.aq-test-ds.password=frank - -mp.messaging.connector.helidon-aq.acknowledge-mode=CLIENT_ACKNOWLEDGE -mp.messaging.connector.helidon-aq.data-source=aq-test-ds - -mp.messaging.outgoing.to-queue-1.connector=helidon-aq -mp.messaging.outgoing.to-queue-1.destination=EXAMPLE_QUEUE_1 -mp.messaging.outgoing.to-queue-1.type=queue - -mp.messaging.incoming.from-queue-1.connector=helidon-aq -mp.messaging.incoming.from-queue-1.destination=EXAMPLE_QUEUE_1 -mp.messaging.incoming.from-queue-1.type=queue - -mp.messaging.outgoing.to-queue-2.connector=helidon-aq -mp.messaging.outgoing.to-queue-2.destination=EXAMPLE_QUEUE_2 -mp.messaging.outgoing.to-queue-2.type=queue - -mp.messaging.incoming.from-queue-2.connector=helidon-aq -mp.messaging.incoming.from-queue-2.destination=EXAMPLE_QUEUE_2 -mp.messaging.incoming.from-queue-2.type=queue - -mp.messaging.incoming.from-byte-queue.connector=helidon-aq -mp.messaging.incoming.from-byte-queue.destination=example_queue_bytes -mp.messaging.incoming.from-byte-queue.type=queue - -mp.messaging.incoming.from-map-queue.connector=helidon-aq -mp.messaging.incoming.from-map-queue.destination=example_queue_map -mp.messaging.incoming.from-map-queue.type=queue diff --git a/examples/messaging/oracle-aq-websocket-mp/src/main/resources/application.yaml b/examples/messaging/oracle-aq-websocket-mp/src/main/resources/application.yaml new file mode 100644 index 000000000..f009f5565 --- /dev/null +++ b/examples/messaging/oracle-aq-websocket-mp/src/main/resources/application.yaml @@ -0,0 +1,68 @@ +# +# Copyright (c) 2024 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. +# + +server: + port: 7001 + host: 0.0.0.0 + + static.classpath: + location: /WEB + welcome: index.html + +javax.sql.DataSource: + aq-test-ds: + connectionFactoryClassName: oracle.jdbc.pool.OracleDataSource + URL: jdbc:oracle:thin:@localhost:1521:XE + user: frank + password: frank + +mp.messaging: + connector: + helidon-aq: + acknowledge-mode: CLIENT_ACKNOWLEDGE + data-source: aq-test-ds + + outgoing: + to-queue-1: + connector: helidon-aq + destination: EXAMPLE_QUEUE_1 + type: queue + + to-queue-2: + connector: helidon-aq + destination: EXAMPLE_QUEUE_2 + type: queue + + incoming: + from-queue-1: + connector: helidon-aq + destination: EXAMPLE_QUEUE_1 + type: queue + + from-queue-2: + connector: helidon-aq + destination: EXAMPLE_QUEUE_2 + type: queue + + from-byte-queue: + connector: helidon-aq + destination: example_queue_bytes + type: queue + + from-map-queue: + connector: helidon-aq + destination: example_queue_map + type: queue diff --git a/examples/messaging/oracle-aq-websocket-mp/src/test/java/io/helidon/examples/messaging/mp/MessagingIT.java b/examples/messaging/oracle-aq-websocket-mp/src/test/java/io/helidon/examples/messaging/mp/MessagingIT.java new file mode 100644 index 000000000..441dec89d --- /dev/null +++ b/examples/messaging/oracle-aq-websocket-mp/src/test/java/io/helidon/examples/messaging/mp/MessagingIT.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2024 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.messaging.mp; + +import java.io.File; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import io.helidon.config.mp.MpConfigSources; +import io.helidon.logging.common.LogConfig; +import io.helidon.microprofile.testing.junit5.Configuration; +import io.helidon.microprofile.testing.junit5.HelidonTest; + +import jakarta.inject.Inject; +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.spi.ConfigProviderResolver; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.images.builder.ImageFromDockerfile; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +@Testcontainers(disabledWithoutDocker = true) +@HelidonTest +@Configuration(useExisting = true) +class MessagingIT { + private static final Logger LOGGER = LoggerFactory.getLogger(MessagingIT.class); + + static { + LogConfig.configureRuntime(); + } + + @Container + static final GenericContainer oracle = + new GenericContainer<>( + new ImageFromDockerfile() + .withFileFromFile("init.sql", new File("../docker/oracle-aq/init.sql")) + .withDockerfileFromBuilder(builder -> builder + .from("container-registry.oracle.com/database/express:latest") + .copy("init.sql", "/opt/oracle/scripts/startup/") + .expose(1521))) + .withExposedPorts(1521) + .waitingFor(Wait.forLogMessage(".*DONE: Executing user defined scripts.*", 1)) + .withLogConsumer(new Slf4jLogConsumer(LOGGER)); + + @Inject + MsgProcessingBean msgProcessingBean; + + @BeforeAll + static void init() { + ConfigProviderResolver cr = ConfigProviderResolver.instance(); + String url = "jdbc:oracle:thin:@localhost:" + oracle.getMappedPort(1521) + ":XE"; + Config c = cr.getBuilder() + .addDefaultSources() + .addDiscoveredSources() + .addDiscoveredConverters() + .withSources(MpConfigSources.create(Map.of( + "config_ordinal", "205", + "server.port", "0", + "mp.initializer.allow", "true", + "javax.sql.DataSource.aq-test-ds.URL", url + ))) + .build(); + cr.registerConfig(c, Thread.currentThread().getContextClassLoader()); + } + + @Test + void testMessage() throws ExecutionException, InterruptedException, TimeoutException { + CompletableFuture future = new CompletableFuture<>(); + msgProcessingBean.subscribeMulti().forEach(future::complete); + msgProcessingBean.process("Test message"); + assertThat(future.get(3, TimeUnit.MINUTES), is("Test message")); + } +} diff --git a/examples/messaging/oracle-aq-websocket-mp/src/test/java/io/helidon/examples/messaging/mp/MessagingTest.java b/examples/messaging/oracle-aq-websocket-mp/src/test/java/io/helidon/examples/messaging/mp/MessagingTest.java new file mode 100644 index 000000000..8458730f4 --- /dev/null +++ b/examples/messaging/oracle-aq-websocket-mp/src/test/java/io/helidon/examples/messaging/mp/MessagingTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024 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.messaging.mp; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import io.helidon.messaging.connectors.aq.AqMessage; +import io.helidon.messaging.connectors.mock.MockConnector; +import io.helidon.messaging.connectors.mock.TestConnector; +import io.helidon.microprofile.testing.junit5.AddConfigBlock; +import io.helidon.microprofile.testing.junit5.HelidonTest; + +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.mock; + +@HelidonTest +@AddConfigBlock(type = "yaml", value = """ + config_ordinal: 205 + + mp.messaging: + outgoing: + to-queue-1: + connector: helidon-mock + destination: EXAMPLE_QUEUE_1 + to-queue-2: + connector: helidon-mock + destination: EXAMPLE_QUEUE_2 + + incoming: + from-queue-1: + connector: helidon-mock + destination: EXAMPLE_QUEUE_1 + from-queue-2: + connector: helidon-mock + destination: EXAMPLE_QUEUE_2 + from-byte-queue: + connector: helidon-mock + destination: example_queue_bytes + from-map-queue: + connector: helidon-mock + destination: example_queue_map + """) +class MessagingTest { + + @Inject + @TestConnector + MockConnector mockConnector; + + @Inject + MsgProcessingBean msgProcessingBean; + + @Test + @SuppressWarnings("unchecked") + void testMessage() throws ExecutionException, InterruptedException, TimeoutException { + // Test channel to-queue-1 + msgProcessingBean.process("Test message"); + mockConnector.outgoing("to-queue-1", String.class) + .request(1) + .assertPayloads("Test message"); + + // Test channel from-queue-2 + CompletableFuture future = new CompletableFuture<>(); + msgProcessingBean.subscribeMulti().log().forEach(future::complete); + + AqMessage aqMessage = (AqMessage) mock(AqMessage.class); + Mockito.when(aqMessage.getPayload()).thenReturn("Test message 2"); + + mockConnector.incoming("from-queue-2", String.class).emit(aqMessage); + assertThat(future.get(15, TimeUnit.SECONDS), is("Test message 2")); + } +} diff --git a/examples/metrics/filtering/se/src/test/java/io/helidon/examples/metrics/filtering/se/MainTest.java b/examples/metrics/filtering/se/src/test/java/io/helidon/examples/metrics/filtering/se/MainTest.java index 4a55a46de..baecb5e7a 100644 --- a/examples/metrics/filtering/se/src/test/java/io/helidon/examples/metrics/filtering/se/MainTest.java +++ b/examples/metrics/filtering/se/src/test/java/io/helidon/examples/metrics/filtering/se/MainTest.java @@ -51,6 +51,8 @@ public MainTest(Http1Client client) { @SetUpServer public static void setup(WebServerConfig.Builder server) { Main.setup(server); + // random port + server.port(-1); } @Test diff --git a/examples/metrics/http-status-count-se/src/test/java/io/helidon/examples/se/httpstatuscount/MainTest.java b/examples/metrics/http-status-count-se/src/test/java/io/helidon/examples/se/httpstatuscount/MainTest.java index 4c1a87659..657de6e2c 100644 --- a/examples/metrics/http-status-count-se/src/test/java/io/helidon/examples/se/httpstatuscount/MainTest.java +++ b/examples/metrics/http-status-count-se/src/test/java/io/helidon/examples/se/httpstatuscount/MainTest.java @@ -52,6 +52,8 @@ public MainTest(Http1Client client) { @SetUpServer public static void setup(WebServerConfig.Builder server) { Main.setup(server); + // random port + server.port(-1); } @Test diff --git a/examples/metrics/kpi/src/test/java/io/helidon/examples/metrics/kpi/MainTest.java b/examples/metrics/kpi/src/test/java/io/helidon/examples/metrics/kpi/MainTest.java index e40b82f88..caf5a5707 100644 --- a/examples/metrics/kpi/src/test/java/io/helidon/examples/metrics/kpi/MainTest.java +++ b/examples/metrics/kpi/src/test/java/io/helidon/examples/metrics/kpi/MainTest.java @@ -52,6 +52,8 @@ public MainTest(Http1Client client) { @SetUpServer public static void setup(WebServerConfig.Builder server) { Main.setup(server); + // random port + server.port(-1); } @Test diff --git a/examples/webserver/opentracing/src/main/java/io/helidon/examples/webserver/opentracing/Main.java b/examples/webserver/opentracing/src/main/java/io/helidon/examples/webserver/opentracing/Main.java index 3282b3b76..e59b5dd39 100644 --- a/examples/webserver/opentracing/src/main/java/io/helidon/examples/webserver/opentracing/Main.java +++ b/examples/webserver/opentracing/src/main/java/io/helidon/examples/webserver/opentracing/Main.java @@ -49,12 +49,14 @@ public static void main(String[] args) { // configure logging in order to not have the standard JVM defaults LogConfig.configureRuntime(); - WebServer server = setupServer(WebServerConfig.builder(), 9411); + WebServer server = setupServer(WebServerConfig.builder(), 9411) + .build() + .start(); System.out.println("Started at http://localhost:" + server.port()); } - static WebServer setupServer(WebServerConfig.Builder builder, int port) { + static WebServerConfig.Builder setupServer(WebServerConfig.Builder builder, int port) { Config config = Config.builder() .sources(ConfigSources.create(Map.of("host", "localhost", "port", "8080"))) @@ -72,8 +74,6 @@ static WebServer setupServer(WebServerConfig.Builder builder, int port) { .build()) .routing(routing -> routing .get("/test", (req, res) -> res.send("Hello World!")) - .post("/hello", (req, res) -> res.send("Hello: " + req.content().as(String.class)))) - .build() - .start(); + .post("/hello", (req, res) -> res.send("Hello: " + req.content().as(String.class)))); } } diff --git a/examples/webserver/opentracing/src/test/java/io/helidon/examples/webserver/opentracing/MainTest.java b/examples/webserver/opentracing/src/test/java/io/helidon/examples/webserver/opentracing/MainTest.java index 9079fd48c..424655fdf 100644 --- a/examples/webserver/opentracing/src/test/java/io/helidon/examples/webserver/opentracing/MainTest.java +++ b/examples/webserver/opentracing/src/test/java/io/helidon/examples/webserver/opentracing/MainTest.java @@ -51,7 +51,11 @@ public class MainTest { @BeforeAll static void checkContainer() { - server = Main.setupServer(WebServer.builder(), container.getMappedPort(9411)); + server = Main.setupServer(WebServer.builder(), container.getMappedPort(9411)) + .port(-1) + .build() + .start(); + client = WebClient.create(config -> config.baseUri("http://localhost:" + server.port()) .addMediaSupport(JsonpSupport.create())); zipkinClient = Http1Client.create(config -> config