diff --git a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/reactive-messaging-codestart/base/README.tpl.qute.md b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/reactive-messaging-codestart/base/README.tpl.qute.md new file mode 100644 index 0000000000000..087035a8a1b22 --- /dev/null +++ b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/reactive-messaging-codestart/base/README.tpl.qute.md @@ -0,0 +1,12 @@ +{#include readme-header /} + +{#each input.selected-extensions-ga} + {#if it.equals("io.quarkus:quarkus-smallrye-reactive-messaging-kafka")} +// TODO : which one to choose ? +[Related Apache Kafka guide section...](https://quarkus.io/guides/kafka) +[Related Apache Kafka guide section...](https://quarkus.io/guides/kafka-reactive-getting-started) + {/if} + {#if it.equals("io.quarkus:quarkus-smallrye-reactive-messaging-amqp")} +[Related Apache AMQP 1.0 guide section...](https://quarkus.io/guides/amqp) + {/if} +{/each} \ No newline at end of file diff --git a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/reactive-messaging-codestart/base/src/main/resources/application.tpl.qute.yml b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/reactive-messaging-codestart/base/src/main/resources/application.tpl.qute.yml new file mode 100644 index 0000000000000..d1ec25a5b62e9 --- /dev/null +++ b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/reactive-messaging-codestart/base/src/main/resources/application.tpl.qute.yml @@ -0,0 +1,135 @@ +{#each input.selected-extensions-ga} + {#if it.equals("io.quarkus:quarkus-smallrye-reactive-messaging-kafka")} + {#if count == 1 } + +mp: + messaging: + outgoing: + source-out: + connector: smallrye-kafka + topic: word + uppercase-out: + connector: smallrye-kafka + topic: uppercase-word + incoming: + source-in: + connector: smallrye-kafka + topic: word + uppercase-in: + connector: smallrye-kafka + topic: uppercase-word + {#else} + +#mp: +# messaging: +# outgoing: +# source-out: +# connector: smallrye-kafka +# topic: word +# uppercase-out: +# connector: smallrye-kafka +# topic: uppercase-word +# incoming: +# source-in: +# connector: smallrye-kafka +# topic: word +# uppercase-in: +# connector: smallrye-kafka +# topic: uppercase-word + {/if} + {/if} + {#if it.equals("io.quarkus:quarkus-smallrye-reactive-messaging-mqtt")} + {#if count == 1 } + +mp: + messaging: + outgoing: + source-out: + connector: smallrye-mqtt + host: localhost + port: '1883' + topic: word + uppercase-out: + connector: smallrye-mqtt + host: localhost + port: '1883' + topic: uppercase-word + incoming: + source-in: + connector: smallrye-mqtt + host: localhost + port: '1883' + topic: word + uppercase-in: + connector: smallrye-mqtt + host: localhost + port: '1883' + topic: uppercase-word + {#else} + +#mp: +# messaging: +# outgoing: +# source-out: +# connector: smallrye-mqtt +# host: localhost +# port: '1883' +# topic: word +# uppercase-out: +# connector: smallrye-mqtt +# host: localhost +# port: '1883' +# topic: uppercase-word +# incoming: +# source-in: +# connector: smallrye-mqtt +# host: localhost +# port: '1883' +# topic: word +# uppercase-in: +# connector: smallrye-mqtt +# host: localhost +# port: '1883' +# topic: uppercase-word + {/if} + {/if} + {#if it.equals("io.quarkus:quarkus-smallrye-reactive-messaging-amqp")} + {#if count == 1 } + +mp: + messaging: + outgoing: + source-out: + address: word + connector: smallrye-amqp + uppercase-out: + connector: smallrye-amqp + address: uppercase-word + incoming: + source-in: + connector: smallrye-amqp + address: word + uppercase-in: + address: uppercase-word + connector: smallrye-amqp + {#else} + +#mp: +# messaging: +# outgoing: +# source-out: +# address: word +# connector: smallrye-amqp +# uppercase-out: +# connector: smallrye-amqp +# address: uppercase-word +# incoming: +# source-in: +# connector: smallrye-amqp +# address: word +# uppercase-in: +# address: uppercase-word +# connector: smallrye-amqp + {/if} + {/if} +{/each} \ No newline at end of file diff --git a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/reactive-messaging-codestart/codestart.yml b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/reactive-messaging-codestart/codestart.yml new file mode 100644 index 0000000000000..1ad7664aa2fe9 --- /dev/null +++ b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/reactive-messaging-codestart/codestart.yml @@ -0,0 +1,12 @@ +name: reactive-messaging-codestart +ref: reactive-messaging +tags: extension-codestart +type: code +metadata: + title: Reactive Messaging codestart + description: Use SmallRye Reactive Messaging +language: + base: + dependencies: + test-dependencies: + - io.smallrye.reactive:smallrye-reactive-messaging-in-memory diff --git a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/reactive-messaging-codestart/java/src/main/java/org/acme/MyReactiveMessagingApplication.java b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/reactive-messaging-codestart/java/src/main/java/org/acme/MyReactiveMessagingApplication.java new file mode 100644 index 0000000000000..3db201f7deca8 --- /dev/null +++ b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/reactive-messaging-codestart/java/src/main/java/org/acme/MyReactiveMessagingApplication.java @@ -0,0 +1,35 @@ +package org.acme; + +import io.quarkus.runtime.StartupEvent; +import org.eclipse.microprofile.reactive.messaging.*; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; +import javax.inject.Inject; +import java.util.stream.Stream; + +@ApplicationScoped +public class MyReactiveMessagingApplication { + + @Inject + @Channel("source-out") + Emitter emitter; + + /** Sends message to the source channel, can be used from a JAX-RS resource or any bean of your application **/ + void onStart(@Observes StartupEvent ev) { + Stream.of("Hello", "with", "SmallRye", "reactive", "message").forEach(string -> emitter.send(string)); + } + + /** Consume the message from the source channel, uppercase it and send it to the uppercase channel **/ + @Incoming("source-in") + @Outgoing("uppercase-out") + public Message toUpperCase(Message message) { + return message.withPayload(message.getPayload().toUpperCase()); + } + + /** Consume the uppercase channel and print the message **/ + @Incoming("uppercase-in") + public void sink(String word) { + System.out.println(">> " + word); + } +} diff --git a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/reactive-messaging-codestart/java/src/test/java/org/acme/MyReactiveMessagingApplicationTest.java b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/reactive-messaging-codestart/java/src/test/java/org/acme/MyReactiveMessagingApplicationTest.java new file mode 100644 index 0000000000000..ac0b73426e5e0 --- /dev/null +++ b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/reactive-messaging-codestart/java/src/test/java/org/acme/MyReactiveMessagingApplicationTest.java @@ -0,0 +1,58 @@ +package org.acme; + +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusTest; +import io.smallrye.reactive.messaging.connectors.InMemoryConnector; +import io.smallrye.reactive.messaging.connectors.InMemorySink; +import io.smallrye.reactive.messaging.connectors.InMemorySource; +import org.junit.jupiter.api.Test; + +import javax.enterprise.inject.Any; +import javax.inject.Inject; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@QuarkusTest +@QuarkusTestResource(MyReactiveMessagingApplicationTest.InMemoryChannelTestResource.class) +class MyReactiveMessagingApplicationTest { + + @Inject + @Any + InMemoryConnector connector; + + @Test + void test() { + InMemorySource source = connector.source("source-in"); + InMemorySink uppercase = connector.sink("uppercase-out"); + + source.send("Hello"); + source.send("In-memory"); + source.send("Connectors"); + + assertEquals(3, uppercase.received().size()); + assertTrue(uppercase.received().stream().anyMatch(message -> message.getPayload().equals("HELLO"))); + assertTrue(uppercase.received().stream().anyMatch(message -> message.getPayload().equals("IN-MEMORY"))); + assertTrue(uppercase.received().stream().anyMatch(message -> message.getPayload().equals("CONNECTORS"))); + + } + + public static class InMemoryChannelTestResource implements QuarkusTestResourceLifecycleManager { + + @Override + public Map start() { + Map env = new HashMap<>(); + env.putAll(InMemoryConnector.switchIncomingChannelsToInMemory("source-in")); + env.putAll(InMemoryConnector.switchOutgoingChannelsToInMemory("uppercase-out")); + return env; + } + + @Override + public void stop() { + InMemoryConnector.clear(); + } + } +} \ No newline at end of file diff --git a/extensions/reactive-messaging-http/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/reactive-messaging-http/runtime/src/main/resources/META-INF/quarkus-extension.yaml index e1b4386991ef7..a02988488bad1 100644 --- a/extensions/reactive-messaging-http/runtime/src/main/resources/META-INF/quarkus-extension.yaml +++ b/extensions/reactive-messaging-http/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -10,4 +10,9 @@ metadata: - "web" - "reactive" - "messaging" - status: "experimental" \ No newline at end of file + status: "experimental" + codestart: + name: "reactive-messaging" + languages: + - "java" + artifact: "io.quarkus:quarkus-project-core-extension-codestarts" \ No newline at end of file diff --git a/extensions/smallrye-reactive-messaging-amqp/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/smallrye-reactive-messaging-amqp/runtime/src/main/resources/META-INF/quarkus-extension.yaml index 977c0d3ae2981..dd55665d3d076 100644 --- a/extensions/smallrye-reactive-messaging-amqp/runtime/src/main/resources/META-INF/quarkus-extension.yaml +++ b/extensions/smallrye-reactive-messaging-amqp/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -14,3 +14,8 @@ metadata: - "mp.messaging." - "quarkus.reactive-messaging." - "quarkus.amqp." + codestart: + name: "reactive-messaging" + languages: + - "java" + artifact: "io.quarkus:quarkus-project-core-extension-codestarts" diff --git a/extensions/smallrye-reactive-messaging-kafka/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/smallrye-reactive-messaging-kafka/runtime/src/main/resources/META-INF/quarkus-extension.yaml index 0d1fc63af6163..16c2f38660922 100644 --- a/extensions/smallrye-reactive-messaging-kafka/runtime/src/main/resources/META-INF/quarkus-extension.yaml +++ b/extensions/smallrye-reactive-messaging-kafka/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -14,3 +14,8 @@ metadata: - "mp.messaging." - "quarkus.reactive-messaging." - "quarkus.kafka." + codestart: + name: "reactive-messaging" + languages: + - "java" + artifact: "io.quarkus:quarkus-project-core-extension-codestarts" diff --git a/extensions/smallrye-reactive-messaging-mqtt/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/smallrye-reactive-messaging-mqtt/runtime/src/main/resources/META-INF/quarkus-extension.yaml index dd61940bd732c..b9b60e7c19a99 100644 --- a/extensions/smallrye-reactive-messaging-mqtt/runtime/src/main/resources/META-INF/quarkus-extension.yaml +++ b/extensions/smallrye-reactive-messaging-mqtt/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -11,3 +11,8 @@ metadata: config: - "mp.messaging." - "quarkus.reactive-messaging." + codestart: + name: "reactive-messaging" + languages: + - "java" + artifact: "io.quarkus:quarkus-project-core-extension-codestarts" diff --git a/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/quarkus/QuarkusCodestartBuildIT.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/quarkus/QuarkusCodestartBuildIT.java index b9bd47007d6f6..7134f453f6d87 100644 --- a/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/quarkus/QuarkusCodestartBuildIT.java +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/quarkus/QuarkusCodestartBuildIT.java @@ -36,7 +36,8 @@ class QuarkusCodestartBuildIT extends PlatformAwareTestBase { private static final Path testDirPath = Paths.get("target/quarkus-codestart-build-test"); - private static final Set EXCLUDED = Sets.newHashSet("spring-web-codestart", "picocli-codestart"); + private static final Set EXCLUDED = Sets.newHashSet("spring-web-codestart", "picocli-codestart", + "reactive-messaging"); @BeforeAll static void setUp() throws IOException { diff --git a/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/quarkus/ReactiveMessagingCodestartIT.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/quarkus/ReactiveMessagingCodestartIT.java new file mode 100644 index 0000000000000..c5952e8d9e5b9 --- /dev/null +++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/quarkus/ReactiveMessagingCodestartIT.java @@ -0,0 +1,35 @@ +package io.quarkus.devtools.codestarts.quarkus; + +import static io.quarkus.devtools.codestarts.quarkus.QuarkusCodestartCatalog.Language.JAVA; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.devtools.testing.codestarts.QuarkusCodestartTest; +import io.quarkus.maven.ArtifactKey; + +public class ReactiveMessagingCodestartIT { + + @RegisterExtension + public static QuarkusCodestartTest codestartTest = QuarkusCodestartTest.builder() + .codestarts("reactive-messaging") + .extension(ArtifactKey.fromString("io.quarkus:quarkus-smallrye-reactive-messaging-kafka")) + .extension(ArtifactKey.fromString("io.quarkus:quarkus-smallrye-reactive-messaging-amqp")) + .extension(ArtifactKey.fromString("io.quarkus:quarkus-smallrye-reactive-messaging-mqtt")) + .languages(JAVA) + .build(); + + @Test + void testContent() throws Throwable { + codestartTest.checkGeneratedSource("org.acme.MyReactiveMessagingApplication"); + // TODO : the generated application.properties is empty + codestartTest.assertThatGeneratedFileMatchSnapshot(JAVA, "src/main/resources/application.properties"); + // TODO : the test class doesn't work using the inner class InMemoryChannelTestResource + codestartTest.checkGeneratedTestSource("org.acme.MyReactiveMessagingApplicationTest"); + } + + @Test + void buildAll() throws Throwable { + codestartTest.buildAllProjects(); + } +} diff --git a/integration-tests/devtools/src/test/resources/__snapshots__/ReactiveMessagingCodestartIT/testContent/src_main_java_ilove_quark_us_MyReactiveMessagingApplication.java b/integration-tests/devtools/src/test/resources/__snapshots__/ReactiveMessagingCodestartIT/testContent/src_main_java_ilove_quark_us_MyReactiveMessagingApplication.java new file mode 100644 index 0000000000000..11e683e6f393f --- /dev/null +++ b/integration-tests/devtools/src/test/resources/__snapshots__/ReactiveMessagingCodestartIT/testContent/src_main_java_ilove_quark_us_MyReactiveMessagingApplication.java @@ -0,0 +1,35 @@ +package ilove.quark.us; + +import io.quarkus.runtime.StartupEvent; +import org.eclipse.microprofile.reactive.messaging.*; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; +import javax.inject.Inject; +import java.util.stream.Stream; + +@ApplicationScoped +public class MyReactiveMessagingApplication { + + @Inject + @Channel("source-out") + Emitter emitter; + + /** Sends message to the source channel, can be used from a JAX-RS resource or any bean of your application **/ + void onStart(@Observes StartupEvent ev) { + Stream.of("Hello", "with", "SmallRye", "reactive", "message").forEach(string -> emitter.send(string)); + } + + /** Consume the message from the source channel, uppercase it and send it to the uppercase channel **/ + @Incoming("source-in") + @Outgoing("uppercase-out") + public Message toUpperCase(Message message) { + return message.withPayload(message.getPayload().toUpperCase()); + } + + /** Consume the uppercase channel and print the message **/ + @Incoming("uppercase-in") + public void sink(String word) { + System.out.println(">> " + word); + } +} diff --git a/integration-tests/devtools/src/test/resources/__snapshots__/ReactiveMessagingCodestartIT/testContent/src_main_resources_application.properties b/integration-tests/devtools/src/test/resources/__snapshots__/ReactiveMessagingCodestartIT/testContent/src_main_resources_application.properties new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/integration-tests/devtools/src/test/resources/__snapshots__/ReactiveMessagingCodestartIT/testContent/src_test_java_ilove_quark_us_MyReactiveMessagingApplicationTest.java b/integration-tests/devtools/src/test/resources/__snapshots__/ReactiveMessagingCodestartIT/testContent/src_test_java_ilove_quark_us_MyReactiveMessagingApplicationTest.java new file mode 100644 index 0000000000000..f3818af8a9fbe --- /dev/null +++ b/integration-tests/devtools/src/test/resources/__snapshots__/ReactiveMessagingCodestartIT/testContent/src_test_java_ilove_quark_us_MyReactiveMessagingApplicationTest.java @@ -0,0 +1,41 @@ +package ilove.quark.us; + +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusTest; +import io.smallrye.reactive.messaging.connectors.InMemoryConnector; +import io.smallrye.reactive.messaging.connectors.InMemorySink; +import io.smallrye.reactive.messaging.connectors.InMemorySource; +import org.junit.jupiter.api.Test; + +import javax.enterprise.inject.Any; +import javax.inject.Inject; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@QuarkusTest +class MyReactiveMessagingApplicationTest { + + @Inject + @Any + InMemoryConnector connector; + + @Test + void test() { + InMemorySource source = connector.source("source-in"); + InMemorySink uppercase = connector.sink("uppercase-out"); + + source.send("Hello"); + source.send("In-memory"); + source.send("Connectors"); + + assertEquals(3, uppercase.received().size()); + assertTrue(uppercase.received().stream().anyMatch(message -> message.getPayload().equals("HELLO"))); + assertTrue(uppercase.received().stream().anyMatch(message -> message.getPayload().equals("IN-MEMORY"))); + assertTrue(uppercase.received().stream().anyMatch(message -> message.getPayload().equals("CONNECTORS"))); + + } +} \ No newline at end of file