diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index fa2327079b292..c6f11ad5bad3f 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -24,7 +24,7 @@ pr:
jobs:
- job: Build_Native_Linux
- timeoutInMinutes: 180
+ timeoutInMinutes: 210
pool:
vmImage: 'Ubuntu 16.04'
diff --git a/bom/deployment/pom.xml b/bom/deployment/pom.xml
index 16bcb6e2224d8..a44b0b50c8f20 100644
--- a/bom/deployment/pom.xml
+++ b/bom/deployment/pom.xml
@@ -96,6 +96,26 @@
quarkus-agroal-deployment
${project.version}
+
+ io.quarkus
+ quarkus-artemis-core
+ ${project.version}
+
+
+ io.quarkus
+ quarkus-artemis-core-deployment
+ ${project.version}
+
+
+ io.quarkus
+ quarkus-artemis-jms
+ ${project.version}
+
+
+ io.quarkus
+ quarkus-artemis-jms-deployment
+ ${project.version}
+
io.quarkus
quarkus-hibernate-validator-deployment
diff --git a/bom/runtime/pom.xml b/bom/runtime/pom.xml
index a3669539b0de3..32798c6707109 100644
--- a/bom/runtime/pom.xml
+++ b/bom/runtime/pom.xml
@@ -150,6 +150,7 @@
2.0.0-alpha03
3.10.2
1.11.0
+ 2.9.0
3.1.0
6.0.1
@@ -277,6 +278,16 @@
quarkus-agroal
${project.version}
+
+ io.quarkus
+ quarkus-artemis-core
+ ${project.version}
+
+
+ io.quarkus
+ quarkus-artemis-jms
+ ${project.version}
+
io.quarkus
quarkus-elasticsearch-rest-client
@@ -1069,6 +1080,16 @@
log4j
${log4j.version}
+
+ org.apache.activemq
+ artemis-core-client
+ ${artemis.version}
+
+
+ org.apache.activemq
+ artemis-jms-client
+ ${artemis.version}
+
org.apache.httpcomponents
httpclient
@@ -2077,7 +2098,7 @@
jetty-webapp
${jetty.version}
-
+
diff --git a/build-parent/pom.xml b/build-parent/pom.xml
index 8507feed43486..411b45acaac48 100644
--- a/build-parent/pom.xml
+++ b/build-parent/pom.xml
@@ -31,6 +31,7 @@
3.3.0
0.0.7
3.7.1
+ 2.9.0
2.3.28
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/builditem/FeatureBuildItem.java b/core/deployment/src/main/java/io/quarkus/deployment/builditem/FeatureBuildItem.java
index 0c02f01f16cc4..896836b8a50e7 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/builditem/FeatureBuildItem.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/builditem/FeatureBuildItem.java
@@ -10,6 +10,8 @@
public final class FeatureBuildItem extends MultiBuildItem {
public static final String AGROAL = "agroal";
+ public static final String ARTEMIS_CORE = "artemis-core";
+ public static final String ARTEMIS_JMS = "artemis-jms";
public static final String CDI = "cdi";
public static final String DYNAMODB = "dynamodb";
public static final String ELASTICSEARCH_REST_CLIENT = "elasticsearch-rest-client";
diff --git a/devtools/common/src/main/filtered/extensions.json b/devtools/common/src/main/filtered/extensions.json
index 54f6769944232..707462898cc47 100644
--- a/devtools/common/src/main/filtered/extensions.json
+++ b/devtools/common/src/main/filtered/extensions.json
@@ -68,6 +68,24 @@
"groupId": "io.quarkus",
"artifactId": "quarkus-amazon-lambda"
},
+ {
+ "name": "Artemis Core",
+ "labels": [
+ "artemis-core",
+ "artemis"
+ ],
+ "groupId": "io.quarkus",
+ "artifactId": "quarkus-artemis-core"
+ },
+ {
+ "name": "Artemis JMS",
+ "labels": [
+ "artemis-jms",
+ "artemis"
+ ],
+ "groupId": "io.quarkus",
+ "artifactId": "quarkus-artemis-jms"
+ },
{
"name": "Flyway",
"labels": [
diff --git a/extensions/artemis-core/deployment/pom.xml b/extensions/artemis-core/deployment/pom.xml
new file mode 100644
index 0000000000000..b5212a74ca088
--- /dev/null
+++ b/extensions/artemis-core/deployment/pom.xml
@@ -0,0 +1,54 @@
+
+
+
+ io.quarkus
+ quarkus-artemis-core-parent
+ 999-SNAPSHOT
+
+ 4.0.0
+
+ quarkus-artemis-core-deployment
+ Quarkus - Artemis - Core - Deployment
+
+
+
+ io.quarkus
+ quarkus-core-deployment
+
+
+
+ io.quarkus
+ quarkus-arc-deployment
+
+
+
+ io.quarkus
+ quarkus-netty-deployment
+
+
+
+ io.quarkus
+ quarkus-artemis-core
+
+
+
+
+
+
+ maven-compiler-plugin
+
+
+
+ io.quarkus
+ quarkus-extension-processor
+ ${project.version}
+
+
+
+
+
+
+
+
diff --git a/extensions/artemis-core/deployment/src/main/java/io/quarkus/artemis/core/deployment/ArtemisCoreProcessor.java b/extensions/artemis-core/deployment/src/main/java/io/quarkus/artemis/core/deployment/ArtemisCoreProcessor.java
new file mode 100644
index 0000000000000..4715c4bb72e8b
--- /dev/null
+++ b/extensions/artemis-core/deployment/src/main/java/io/quarkus/artemis/core/deployment/ArtemisCoreProcessor.java
@@ -0,0 +1,100 @@
+package io.quarkus.artemis.core.deployment;
+
+import java.util.Collection;
+import java.util.Optional;
+
+import org.apache.activemq.artemis.api.core.client.loadbalance.ConnectionLoadBalancingPolicy;
+import org.apache.activemq.artemis.api.core.client.loadbalance.FirstElementConnectionLoadBalancingPolicy;
+import org.apache.activemq.artemis.api.core.client.loadbalance.RandomConnectionLoadBalancingPolicy;
+import org.apache.activemq.artemis.api.core.client.loadbalance.RandomStickyConnectionLoadBalancingPolicy;
+import org.apache.activemq.artemis.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy;
+import org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnectorFactory;
+import org.apache.activemq.artemis.spi.core.remoting.ConnectorFactory;
+import org.apache.commons.logging.impl.Jdk14Logger;
+import org.apache.commons.logging.impl.LogFactoryImpl;
+import org.jboss.jandex.ClassInfo;
+import org.jboss.jandex.DotName;
+import org.jboss.logging.Logger;
+
+import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
+import io.quarkus.arc.deployment.BeanContainerBuildItem;
+import io.quarkus.artemis.core.runtime.ArtemisCoreProducer;
+import io.quarkus.artemis.core.runtime.ArtemisCoreRecorder;
+import io.quarkus.artemis.core.runtime.ArtemisRuntimeConfig;
+import io.quarkus.deployment.annotations.BuildProducer;
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.annotations.ExecutionTime;
+import io.quarkus.deployment.annotations.Record;
+import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
+import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.deployment.builditem.substrate.ReflectiveClassBuildItem;
+
+public class ArtemisCoreProcessor {
+
+ private static final Logger LOGGER = Logger.getLogger(ArtemisCoreProcessor.class);
+
+ static final Class[] BUILTIN_CONNECTOR_FACTORIES = {
+ NettyConnectorFactory.class
+ };
+
+ static final Class[] BUILTIN_LOADBALANCING_POLICIES = {
+ FirstElementConnectionLoadBalancingPolicy.class,
+ RandomConnectionLoadBalancingPolicy.class,
+ RandomStickyConnectionLoadBalancingPolicy.class,
+ RoundRobinConnectionLoadBalancingPolicy.class
+ };
+
+ @BuildStep
+ void build(CombinedIndexBuildItem indexBuildItem,
+ BuildProducer reflectiveClass) {
+
+ reflectiveClass.produce(new ReflectiveClassBuildItem(false, false,
+ LogFactoryImpl.class.getName(), Jdk14Logger.class.getName()));
+
+ Collection connectorFactories = indexBuildItem.getIndex()
+ .getAllKnownImplementors(DotName.createSimple(ConnectorFactory.class.getName()));
+
+ for (ClassInfo ci : connectorFactories) {
+ LOGGER.debug("Adding reflective class " + ci);
+ reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, ci.toString()));
+ }
+
+ for (Class c : BUILTIN_CONNECTOR_FACTORIES) {
+ reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, c));
+ }
+
+ Collection loadBalancers = indexBuildItem.getIndex()
+ .getAllKnownImplementors(DotName.createSimple(ConnectionLoadBalancingPolicy.class.getName()));
+
+ for (ClassInfo ci : loadBalancers) {
+ LOGGER.debug("Adding reflective class " + ci);
+ reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, ci.toString()));
+ }
+
+ for (Class c : BUILTIN_LOADBALANCING_POLICIES) {
+ reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, c));
+ }
+ }
+
+ @BuildStep
+ void load(BuildProducer additionalBean, BuildProducer feature,
+ Optional artemisJms) {
+
+ if (artemisJms.isPresent()) {
+ return;
+ }
+ feature.produce(new FeatureBuildItem(FeatureBuildItem.ARTEMIS_CORE));
+ additionalBean.produce(AdditionalBeanBuildItem.unremovableOf(ArtemisCoreProducer.class));
+ }
+
+ @Record(ExecutionTime.RUNTIME_INIT)
+ @BuildStep
+ void configure(ArtemisCoreRecorder recorder, ArtemisRuntimeConfig runtimeConfig,
+ BeanContainerBuildItem beanContainer, Optional artemisJms) {
+
+ if (artemisJms.isPresent()) {
+ return;
+ }
+ recorder.setConfig(runtimeConfig, beanContainer.getValue());
+ }
+}
diff --git a/extensions/artemis-core/deployment/src/main/java/io/quarkus/artemis/core/deployment/ArtemisJmsBuildItem.java b/extensions/artemis-core/deployment/src/main/java/io/quarkus/artemis/core/deployment/ArtemisJmsBuildItem.java
new file mode 100644
index 0000000000000..71aaf27395ac9
--- /dev/null
+++ b/extensions/artemis-core/deployment/src/main/java/io/quarkus/artemis/core/deployment/ArtemisJmsBuildItem.java
@@ -0,0 +1,9 @@
+package io.quarkus.artemis.core.deployment;
+
+import io.quarkus.builder.item.SimpleBuildItem;
+
+/**
+ * Marker build item indicating that JMS is enabled
+ */
+public final class ArtemisJmsBuildItem extends SimpleBuildItem {
+}
diff --git a/extensions/artemis-core/pom.xml b/extensions/artemis-core/pom.xml
new file mode 100644
index 0000000000000..6136f616664b2
--- /dev/null
+++ b/extensions/artemis-core/pom.xml
@@ -0,0 +1,21 @@
+
+
+
+ quarkus-build-parent
+ io.quarkus
+ 999-SNAPSHOT
+ ../../build-parent/pom.xml
+
+
+ 4.0.0
+ quarkus-artemis-core-parent
+ Quarkus - Artemis - Core
+ pom
+
+
+ deployment
+ runtime
+
+
diff --git a/extensions/artemis-core/runtime/pom.xml b/extensions/artemis-core/runtime/pom.xml
new file mode 100644
index 0000000000000..cdf0130ac4ac4
--- /dev/null
+++ b/extensions/artemis-core/runtime/pom.xml
@@ -0,0 +1,64 @@
+
+
+
+ io.quarkus
+ quarkus-artemis-core-parent
+ 999-SNAPSHOT
+
+ 4.0.0
+
+ quarkus-artemis-core
+ Quarkus - Artemis - Core - Runtime
+
+
+
+ io.quarkus
+ quarkus-core
+
+
+
+ io.quarkus
+ quarkus-arc
+
+
+
+ io.quarkus
+ quarkus-netty
+
+
+
+ org.apache.activemq
+ artemis-core-client
+
+
+
+ com.oracle.substratevm
+ svm
+
+
+
+
+
+
+
+ io.quarkus
+ quarkus-bootstrap-maven-plugin
+
+
+ maven-compiler-plugin
+
+
+
+ io.quarkus
+ quarkus-extension-processor
+ ${project.version}
+
+
+
+
+
+
+
+
diff --git a/extensions/artemis-core/runtime/src/main/java/io/quarkus/artemis/core/runtime/ArtemisCoreProducer.java b/extensions/artemis-core/runtime/src/main/java/io/quarkus/artemis/core/runtime/ArtemisCoreProducer.java
new file mode 100644
index 0000000000000..44fa7a1d580d6
--- /dev/null
+++ b/extensions/artemis-core/runtime/src/main/java/io/quarkus/artemis/core/runtime/ArtemisCoreProducer.java
@@ -0,0 +1,26 @@
+package io.quarkus.artemis.core.runtime;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Produces;
+
+import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
+import org.apache.activemq.artemis.api.core.client.ServerLocator;
+
+@ApplicationScoped
+public class ArtemisCoreProducer {
+
+ private ArtemisRuntimeConfig config;
+
+ @Produces
+ public ServerLocator produceServerLocator() throws Exception {
+ return ActiveMQClient.createServerLocator(config.url);
+ }
+
+ public ArtemisRuntimeConfig getConfig() {
+ return config;
+ }
+
+ public void setConfig(ArtemisRuntimeConfig config) {
+ this.config = config;
+ }
+}
diff --git a/extensions/artemis-core/runtime/src/main/java/io/quarkus/artemis/core/runtime/ArtemisCoreRecorder.java b/extensions/artemis-core/runtime/src/main/java/io/quarkus/artemis/core/runtime/ArtemisCoreRecorder.java
new file mode 100644
index 0000000000000..654e08d7c6a04
--- /dev/null
+++ b/extensions/artemis-core/runtime/src/main/java/io/quarkus/artemis/core/runtime/ArtemisCoreRecorder.java
@@ -0,0 +1,12 @@
+package io.quarkus.artemis.core.runtime;
+
+import io.quarkus.arc.runtime.BeanContainer;
+import io.quarkus.runtime.annotations.Recorder;
+
+@Recorder
+public class ArtemisCoreRecorder {
+
+ public void setConfig(ArtemisRuntimeConfig config, BeanContainer container) {
+ container.instance(ArtemisCoreProducer.class).setConfig(config);
+ }
+}
diff --git a/extensions/artemis-core/runtime/src/main/java/io/quarkus/artemis/core/runtime/ArtemisRuntimeConfig.java b/extensions/artemis-core/runtime/src/main/java/io/quarkus/artemis/core/runtime/ArtemisRuntimeConfig.java
new file mode 100644
index 0000000000000..848597a230d99
--- /dev/null
+++ b/extensions/artemis-core/runtime/src/main/java/io/quarkus/artemis/core/runtime/ArtemisRuntimeConfig.java
@@ -0,0 +1,29 @@
+package io.quarkus.artemis.core.runtime;
+
+import java.util.Optional;
+
+import io.quarkus.runtime.annotations.ConfigItem;
+import io.quarkus.runtime.annotations.ConfigPhase;
+import io.quarkus.runtime.annotations.ConfigRoot;
+
+@ConfigRoot(name = "artemis", phase = ConfigPhase.RUN_TIME)
+public class ArtemisRuntimeConfig {
+
+ /**
+ * Artemis connection url
+ */
+ @ConfigItem
+ public String url;
+
+ /**
+ * Username for authentication, only used with JMS
+ */
+ @ConfigItem
+ public Optional username;
+
+ /**
+ * Password for authentication, only used with JMS
+ */
+ @ConfigItem
+ public Optional password;
+}
diff --git a/extensions/artemis-core/runtime/src/main/java/io/quarkus/artemis/core/runtime/graal/CheckDependenciesSubstitutions.java b/extensions/artemis-core/runtime/src/main/java/io/quarkus/artemis/core/runtime/graal/CheckDependenciesSubstitutions.java
new file mode 100644
index 0000000000000..7d3879bfc1b58
--- /dev/null
+++ b/extensions/artemis-core/runtime/src/main/java/io/quarkus/artemis/core/runtime/graal/CheckDependenciesSubstitutions.java
@@ -0,0 +1,20 @@
+package io.quarkus.artemis.core.runtime.graal;
+
+import com.oracle.svm.core.annotate.Substitute;
+import com.oracle.svm.core.annotate.TargetClass;
+
+// Epoll and Kqueue are not supported on SVM
+@Substitute
+@TargetClass(org.apache.activemq.artemis.core.remoting.impl.netty.CheckDependencies.class)
+final class CheckDependenciesSubstitutions {
+
+ @Substitute
+ public static final boolean isEpollAvailable() {
+ return false;
+ }
+
+ @Substitute
+ public static final boolean isKQueueAvailable() {
+ return false;
+ }
+}
diff --git a/extensions/artemis-jms/deployment/pom.xml b/extensions/artemis-jms/deployment/pom.xml
new file mode 100644
index 0000000000000..039f864fb8cce
--- /dev/null
+++ b/extensions/artemis-jms/deployment/pom.xml
@@ -0,0 +1,44 @@
+
+
+
+ io.quarkus
+ quarkus-artemis-jms-parent
+ 999-SNAPSHOT
+
+ 4.0.0
+
+ quarkus-artemis-jms-deployment
+ Quarkus - Artemis - JMS - Deployment
+
+
+
+ io.quarkus
+ quarkus-artemis-core-deployment
+
+
+
+ io.quarkus
+ quarkus-artemis-jms
+
+
+
+
+
+
+ maven-compiler-plugin
+
+
+
+ io.quarkus
+ quarkus-extension-processor
+ ${project.version}
+
+
+
+
+
+
+
+
diff --git a/extensions/artemis-jms/deployment/src/main/java/io/quarkus/artemis/jms/deployment/ArtemisJmsProcessor.java b/extensions/artemis-jms/deployment/src/main/java/io/quarkus/artemis/jms/deployment/ArtemisJmsProcessor.java
new file mode 100644
index 0000000000000..9890871e44af2
--- /dev/null
+++ b/extensions/artemis-jms/deployment/src/main/java/io/quarkus/artemis/jms/deployment/ArtemisJmsProcessor.java
@@ -0,0 +1,33 @@
+package io.quarkus.artemis.jms.deployment;
+
+import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
+import io.quarkus.arc.deployment.BeanContainerBuildItem;
+import io.quarkus.artemis.core.deployment.ArtemisJmsBuildItem;
+import io.quarkus.artemis.core.runtime.ArtemisRuntimeConfig;
+import io.quarkus.artemis.jms.runtime.ArtemisJmsProducer;
+import io.quarkus.artemis.jms.runtime.ArtemisJmsRecorder;
+import io.quarkus.deployment.annotations.BuildProducer;
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.annotations.ExecutionTime;
+import io.quarkus.deployment.annotations.Record;
+import io.quarkus.deployment.builditem.FeatureBuildItem;
+
+public class ArtemisJmsProcessor {
+
+ @BuildStep
+ void load(BuildProducer additionalBean, BuildProducer feature,
+ BuildProducer artemisJms) {
+
+ artemisJms.produce(new ArtemisJmsBuildItem());
+ feature.produce(new FeatureBuildItem(FeatureBuildItem.ARTEMIS_JMS));
+ additionalBean.produce(AdditionalBeanBuildItem.unremovableOf(ArtemisJmsProducer.class));
+ }
+
+ @Record(ExecutionTime.RUNTIME_INIT)
+ @BuildStep
+ void configure(ArtemisJmsRecorder recorder, ArtemisRuntimeConfig runtimeConfig,
+ BeanContainerBuildItem beanContainer) {
+
+ recorder.setConfig(runtimeConfig, beanContainer.getValue());
+ }
+}
diff --git a/extensions/artemis-jms/pom.xml b/extensions/artemis-jms/pom.xml
new file mode 100644
index 0000000000000..73b6fa958f5d1
--- /dev/null
+++ b/extensions/artemis-jms/pom.xml
@@ -0,0 +1,21 @@
+
+
+
+ quarkus-build-parent
+ io.quarkus
+ 999-SNAPSHOT
+ ../../build-parent/pom.xml
+
+
+ 4.0.0
+ quarkus-artemis-jms-parent
+ Quarkus - Artemis - JMS
+ pom
+
+
+ deployment
+ runtime
+
+
diff --git a/extensions/artemis-jms/runtime/pom.xml b/extensions/artemis-jms/runtime/pom.xml
new file mode 100644
index 0000000000000..dd998a08444dc
--- /dev/null
+++ b/extensions/artemis-jms/runtime/pom.xml
@@ -0,0 +1,49 @@
+
+
+
+ io.quarkus
+ quarkus-artemis-jms-parent
+ 999-SNAPSHOT
+
+ 4.0.0
+
+ quarkus-artemis-jms
+ Quarkus - Artemis - JMS - Runtime
+
+
+
+ io.quarkus
+ quarkus-artemis-core
+
+
+
+ org.apache.activemq
+ artemis-jms-client
+
+
+
+
+
+
+
+ io.quarkus
+ quarkus-bootstrap-maven-plugin
+
+
+ maven-compiler-plugin
+
+
+
+ io.quarkus
+ quarkus-extension-processor
+ ${project.version}
+
+
+
+
+
+
+
+
diff --git a/extensions/artemis-jms/runtime/src/main/java/io/quarkus/artemis/jms/runtime/ArtemisJmsProducer.java b/extensions/artemis-jms/runtime/src/main/java/io/quarkus/artemis/jms/runtime/ArtemisJmsProducer.java
new file mode 100644
index 0000000000000..a02a085871013
--- /dev/null
+++ b/extensions/artemis-jms/runtime/src/main/java/io/quarkus/artemis/jms/runtime/ArtemisJmsProducer.java
@@ -0,0 +1,29 @@
+package io.quarkus.artemis.jms.runtime;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Produces;
+import javax.jms.ConnectionFactory;
+
+import org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory;
+
+import io.quarkus.artemis.core.runtime.ArtemisRuntimeConfig;
+
+@ApplicationScoped
+public class ArtemisJmsProducer {
+
+ private ArtemisRuntimeConfig config;
+
+ @Produces
+ public ConnectionFactory producesConnectionFactory() {
+ return new ActiveMQJMSConnectionFactory(config.url,
+ config.username.orElse(null), config.password.orElse(null));
+ }
+
+ public ArtemisRuntimeConfig getConfig() {
+ return config;
+ }
+
+ public void setConfig(ArtemisRuntimeConfig config) {
+ this.config = config;
+ }
+}
diff --git a/extensions/artemis-jms/runtime/src/main/java/io/quarkus/artemis/jms/runtime/ArtemisJmsRecorder.java b/extensions/artemis-jms/runtime/src/main/java/io/quarkus/artemis/jms/runtime/ArtemisJmsRecorder.java
new file mode 100644
index 0000000000000..fffef19ee8396
--- /dev/null
+++ b/extensions/artemis-jms/runtime/src/main/java/io/quarkus/artemis/jms/runtime/ArtemisJmsRecorder.java
@@ -0,0 +1,13 @@
+package io.quarkus.artemis.jms.runtime;
+
+import io.quarkus.arc.runtime.BeanContainer;
+import io.quarkus.artemis.core.runtime.ArtemisRuntimeConfig;
+import io.quarkus.runtime.annotations.Recorder;
+
+@Recorder
+public class ArtemisJmsRecorder {
+
+ public void setConfig(ArtemisRuntimeConfig config, BeanContainer container) {
+ container.instance(ArtemisJmsProducer.class).setConfig(config);
+ }
+}
diff --git a/extensions/infinispan-client/deployment/src/main/java/io/quarkus/infinispan/client/deployment/InfinispanClientProcessor.java b/extensions/infinispan-client/deployment/src/main/java/io/quarkus/infinispan/client/deployment/InfinispanClientProcessor.java
index 13200477c7679..62b8131f2d4b3 100644
--- a/extensions/infinispan-client/deployment/src/main/java/io/quarkus/infinispan/client/deployment/InfinispanClientProcessor.java
+++ b/extensions/infinispan-client/deployment/src/main/java/io/quarkus/infinispan/client/deployment/InfinispanClientProcessor.java
@@ -48,6 +48,7 @@
import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem;
import io.quarkus.deployment.builditem.SystemPropertyBuildItem;
import io.quarkus.deployment.builditem.substrate.ReflectiveClassBuildItem;
+import io.quarkus.deployment.builditem.substrate.SubstrateConfigBuildItem;
import io.quarkus.infinispan.client.runtime.InfinispanClientBuildTimeConfig;
import io.quarkus.infinispan.client.runtime.InfinispanClientProducer;
import io.quarkus.infinispan.client.runtime.InfinispanClientRuntimeConfig;
@@ -73,6 +74,7 @@ InfinispanPropertiesBuildItem setup(ApplicationArchivesBuildItem applicationArch
BuildProducer feature,
BuildProducer additionalBeans,
BuildProducer sslNativeSupport,
+ BuildProducer substrateConfig,
ApplicationIndexBuildItem applicationIndexBuildItem) throws ClassNotFoundException, IOException {
feature.produce(new FeatureBuildItem(FeatureBuildItem.INFINISPAN_CLIENT));
@@ -154,6 +156,9 @@ InfinispanPropertiesBuildItem setup(ApplicationArchivesBuildItem applicationArch
// This is required for netty to work properly
reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, "io.netty.channel.socket.nio.NioSocketChannel"));
+ substrateConfig.produce(SubstrateConfigBuildItem.builder()
+ .addRuntimeInitializedClass("org.infinispan.client.hotrod.impl.transport.netty.TransportHelper")
+ .build());
// We use reflection to have continuous queries work
reflectiveClass.produce(new ReflectiveClassBuildItem(true, false,
"org.infinispan.client.hotrod.event.impl.ContinuousQueryImpl$ClientEntryListener"));
diff --git a/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java b/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java
index ea17730947fa2..33946a8b60c1e 100644
--- a/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java
+++ b/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java
@@ -13,6 +13,7 @@
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
+import io.quarkus.deployment.builditem.JniBuildItem;
import io.quarkus.deployment.builditem.substrate.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.substrate.SubstrateConfigBuildItem;
import io.quarkus.netty.BossGroup;
@@ -26,7 +27,9 @@ class NettyProcessor {
private static final Logger log = Logger.getLogger(NettyProcessor.class);
@BuildStep
- SubstrateConfigBuildItem build() {
+ SubstrateConfigBuildItem build(BuildProducer jni) {
+ boolean enableJni = false;
+
reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, "io.netty.channel.socket.nio.NioSocketChannel"));
reflectiveClass
.produce(new ReflectiveClassBuildItem(false, false, "io.netty.channel.socket.nio.NioServerSocketChannel"));
@@ -48,6 +51,47 @@ SubstrateConfigBuildItem build() {
//ignore
log.debug("Not registering Netty HTTP classes as they were not found");
}
+
+ try {
+ Class.forName("io.netty.channel.unix.UnixChannel");
+ enableJni = true;
+ builder.addRuntimeInitializedClass("io.netty.channel.unix.Errors")
+ .addRuntimeInitializedClass("io.netty.channel.unix.FileDescriptor")
+ .addRuntimeInitializedClass("io.netty.channel.unix.IovArray")
+ .addRuntimeInitializedClass("io.netty.channel.unix.Limits");
+ } catch (ClassNotFoundException e) {
+ //ignore
+ log.debug("Not registering Netty native unix classes as they were not found");
+ }
+
+ try {
+ Class.forName("io.netty.channel.epoll.EpollMode");
+ enableJni = true;
+ builder.addRuntimeInitializedClass("io.netty.channel.epoll.Epoll")
+ .addRuntimeInitializedClass("io.netty.channel.epoll.EpollEventArray")
+ .addRuntimeInitializedClass("io.netty.channel.epoll.EpollEventLoop")
+ .addRuntimeInitializedClass("io.netty.channel.epoll.Native");
+ } catch (ClassNotFoundException e) {
+ //ignore
+ log.debug("Not registering Netty native epoll classes as they were not found");
+ }
+
+ try {
+ Class.forName("io.netty.channel.kqueue.AcceptFilter");
+ enableJni = true;
+ builder.addRuntimeInitializedClass("io.netty.channel.kqueue.KQueue")
+ .addRuntimeInitializedClass("io.netty.channel.kqueue.KQueueEventArray")
+ .addRuntimeInitializedClass("io.netty.channel.kqueue.KQueueEventLoop")
+ .addRuntimeInitializedClass("io.netty.channel.kqueue.Native");
+ } catch (ClassNotFoundException e) {
+ //ignore
+ log.debug("Not registering Netty native kqueue classes as they were not found");
+ }
+
+ if (enableJni) {
+ jni.produce(new JniBuildItem());
+ }
+
return builder //TODO: make configurable
.build();
}
diff --git a/extensions/pom.xml b/extensions/pom.xml
index a13ac3afce6c2..ba0c56d0fa191 100644
--- a/extensions/pom.xml
+++ b/extensions/pom.xml
@@ -74,6 +74,8 @@
tika
neo4j
mongodb-client
+ artemis-core
+ artemis-jms
spring-di
diff --git a/integration-tests/artemis-core/pom.xml b/integration-tests/artemis-core/pom.xml
new file mode 100644
index 0000000000000..9a204f4d6e7c4
--- /dev/null
+++ b/integration-tests/artemis-core/pom.xml
@@ -0,0 +1,127 @@
+
+
+
+ quarkus-integration-tests-parent
+ io.quarkus
+ 999-SNAPSHOT
+
+ 4.0.0
+
+ quarkus-integration-test-artemis-core
+ Quarkus - Integration Tests - Artemis - Core
+ The Apache ActiveMQ Artemis Core integration tests module
+
+
+ true
+
+
+
+
+
+ io.quarkus
+ quarkus-resteasy
+
+
+
+
+ io.quarkus
+ quarkus-artemis-core
+
+
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+ io.rest-assured
+ rest-assured
+ test
+
+
+ org.apache.activemq
+ artemis-server
+ ${artemis.version}
+ test
+
+
+ org.jboss.logmanager
+ jboss-logmanager
+
+
+
+
+
+
+
+
+ ${project.groupId}
+ quarkus-maven-plugin
+
+
+
+ build
+
+
+
+
+
+
+
+
+
+ native-image
+
+
+ native
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ integration-test
+ verify
+
+
+
+ ${project.build.directory}/${project.build.finalName}-runner
+
+
+
+
+
+
+ ${project.groupId}
+ quarkus-maven-plugin
+
+
+ native-image
+
+ native-image
+
+
+ true
+ true
+
+ ${graalvmHome}
+
+
+
+
+
+
+
+
+
+
diff --git a/integration-tests/artemis-core/src/main/java/io/quarkus/it/artemis/ArtemisConsumerManager.java b/integration-tests/artemis-core/src/main/java/io/quarkus/it/artemis/ArtemisConsumerManager.java
new file mode 100644
index 0000000000000..3f0bcff7408cf
--- /dev/null
+++ b/integration-tests/artemis-core/src/main/java/io/quarkus/it/artemis/ArtemisConsumerManager.java
@@ -0,0 +1,36 @@
+package io.quarkus.it.artemis;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import org.apache.activemq.artemis.api.core.ActiveMQException;
+import org.apache.activemq.artemis.api.core.client.ClientMessage;
+import org.apache.activemq.artemis.api.core.client.ClientSession;
+import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
+import org.apache.activemq.artemis.api.core.client.ServerLocator;
+
+@ApplicationScoped
+public class ArtemisConsumerManager {
+
+ @Inject
+ ServerLocator serverLocator;
+
+ private ClientSessionFactory connection;
+
+ @PostConstruct
+ public void init() throws Exception {
+ connection = serverLocator.createSessionFactory();
+ }
+
+ public String receive() {
+ try (ClientSession session = connection.createSession()) {
+ session.start();
+ ClientMessage message = session.createConsumer("test-core").receive(1000L);
+ message.acknowledge();
+ return message.getBodyBuffer().readString();
+ } catch (ActiveMQException e) {
+ throw new RuntimeException("Could not receive message", e);
+ }
+ }
+}
diff --git a/integration-tests/artemis-core/src/main/java/io/quarkus/it/artemis/ArtemisEndpoint.java b/integration-tests/artemis-core/src/main/java/io/quarkus/it/artemis/ArtemisEndpoint.java
new file mode 100644
index 0000000000000..09fcc62d76fd6
--- /dev/null
+++ b/integration-tests/artemis-core/src/main/java/io/quarkus/it/artemis/ArtemisEndpoint.java
@@ -0,0 +1,26 @@
+package io.quarkus.it.artemis;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+@Path("/artemis")
+public class ArtemisEndpoint {
+
+ @Inject
+ ArtemisProducerManager producer;
+
+ @Inject
+ ArtemisConsumerManager consumer;
+
+ @POST
+ public void post(String message) {
+ producer.send(message);
+ }
+
+ @GET
+ public String get() {
+ return consumer.receive();
+ }
+}
diff --git a/integration-tests/artemis-core/src/main/java/io/quarkus/it/artemis/ArtemisProducerManager.java b/integration-tests/artemis-core/src/main/java/io/quarkus/it/artemis/ArtemisProducerManager.java
new file mode 100644
index 0000000000000..c2dc9f9db748f
--- /dev/null
+++ b/integration-tests/artemis-core/src/main/java/io/quarkus/it/artemis/ArtemisProducerManager.java
@@ -0,0 +1,35 @@
+package io.quarkus.it.artemis;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+import org.apache.activemq.artemis.api.core.ActiveMQException;
+import org.apache.activemq.artemis.api.core.client.ClientMessage;
+import org.apache.activemq.artemis.api.core.client.ClientSession;
+import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
+import org.apache.activemq.artemis.api.core.client.ServerLocator;
+
+@ApplicationScoped
+public class ArtemisProducerManager {
+
+ @Inject
+ ServerLocator serverLocator;
+
+ private ClientSessionFactory connection;
+
+ @PostConstruct
+ public void init() throws Exception {
+ connection = serverLocator.createSessionFactory();
+ }
+
+ public void send(String body) {
+ try (ClientSession session = connection.createSession()) {
+ ClientMessage message = session.createMessage(true);
+ message.getBodyBuffer().writeString(body);
+ session.createProducer("test-core").send(message);
+ } catch (ActiveMQException e) {
+ throw new RuntimeException("Could not send message", e);
+ }
+ }
+}
diff --git a/integration-tests/artemis-core/src/main/resources/application.properties b/integration-tests/artemis-core/src/main/resources/application.properties
new file mode 100644
index 0000000000000..d7f1552f7a3ae
--- /dev/null
+++ b/integration-tests/artemis-core/src/main/resources/application.properties
@@ -0,0 +1 @@
+quarkus.artemis.url=tcp://localhost:61616
diff --git a/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisConsumerITCase.java b/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisConsumerITCase.java
new file mode 100644
index 0000000000000..062348efe2579
--- /dev/null
+++ b/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisConsumerITCase.java
@@ -0,0 +1,8 @@
+package io.quarkus.it.artemis;
+
+import io.quarkus.test.junit.SubstrateTest;
+
+@SubstrateTest
+public class ArtemisConsumerITCase extends ArtemisConsumerTest {
+
+}
diff --git a/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisConsumerTest.java b/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisConsumerTest.java
new file mode 100644
index 0000000000000..6c1bee7d93462
--- /dev/null
+++ b/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisConsumerTest.java
@@ -0,0 +1,31 @@
+package io.quarkus.it.artemis;
+
+import org.apache.activemq.artemis.api.core.client.ClientMessage;
+import org.apache.activemq.artemis.api.core.client.ClientSession;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import io.restassured.response.Response;
+import io.undertow.httpcore.StatusCodes;
+
+@QuarkusTest
+@QuarkusTestResource(ArtemisTestResource.class)
+public class ArtemisConsumerTest implements ArtemisHelper {
+
+ @Test
+ public void test() throws Exception {
+ String body = createBody();
+ try (ClientSession session = createSession()) {
+ ClientMessage message = session.createMessage(true);
+ message.getBodyBuffer().writeString(body);
+ session.createProducer("test-core").send(message);
+ }
+
+ Response response = RestAssured.with().body(body).get("/artemis");
+ Assertions.assertEquals(StatusCodes.OK, response.statusCode());
+ Assertions.assertEquals(body, response.getBody().asString());
+ }
+}
diff --git a/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisHelper.java b/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisHelper.java
new file mode 100644
index 0000000000000..da1b14a8a2566
--- /dev/null
+++ b/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisHelper.java
@@ -0,0 +1,17 @@
+package io.quarkus.it.artemis;
+
+import java.util.Random;
+
+import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
+import org.apache.activemq.artemis.api.core.client.ClientSession;
+
+public interface ArtemisHelper {
+
+ default String createBody() {
+ return Integer.toString(new Random().nextInt(Integer.MAX_VALUE), 16);
+ }
+
+ default ClientSession createSession() throws Exception {
+ return ActiveMQClient.createServerLocator("tcp://localhost:61616").createSessionFactory().createSession();
+ }
+}
diff --git a/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisProducerITCase.java b/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisProducerITCase.java
new file mode 100644
index 0000000000000..d8aea4c888df5
--- /dev/null
+++ b/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisProducerITCase.java
@@ -0,0 +1,8 @@
+package io.quarkus.it.artemis;
+
+import io.quarkus.test.junit.SubstrateTest;
+
+@SubstrateTest
+public class ArtemisProducerITCase extends ArtemisProducerTest {
+
+}
diff --git a/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisProducerTest.java b/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisProducerTest.java
new file mode 100644
index 0000000000000..609b1d2567f93
--- /dev/null
+++ b/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisProducerTest.java
@@ -0,0 +1,31 @@
+package io.quarkus.it.artemis;
+
+import org.apache.activemq.artemis.api.core.client.ClientMessage;
+import org.apache.activemq.artemis.api.core.client.ClientSession;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import io.restassured.response.Response;
+import io.undertow.httpcore.StatusCodes;
+
+@QuarkusTest
+@QuarkusTestResource(ArtemisTestResource.class)
+public class ArtemisProducerTest implements ArtemisHelper {
+
+ @Test
+ public void test() throws Exception {
+ String body = createBody();
+ Response response = RestAssured.with().body(body).post("/artemis");
+ Assertions.assertEquals(StatusCodes.NO_CONTENT, response.statusCode());
+
+ try (ClientSession session = createSession()) {
+ session.start();
+ ClientMessage message = session.createConsumer("test-core").receive(1000L);
+ message.acknowledge();
+ Assertions.assertEquals(body, message.getBodyBuffer().readString());
+ }
+ }
+}
diff --git a/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisTestResource.java b/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisTestResource.java
new file mode 100644
index 0000000000000..581cde9b6f67d
--- /dev/null
+++ b/integration-tests/artemis-core/src/test/java/io/quarkus/it/artemis/ArtemisTestResource.java
@@ -0,0 +1,36 @@
+package io.quarkus.it.artemis;
+
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
+import org.apache.commons.io.FileUtils;
+
+import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
+
+public class ArtemisTestResource implements QuarkusTestResourceLifecycleManager {
+
+ private EmbeddedActiveMQ embedded;
+
+ @Override
+ public Map start() {
+ try {
+ FileUtils.deleteDirectory(Paths.get("./target/artemis").toFile());
+ embedded = new EmbeddedActiveMQ();
+ embedded.start();
+ } catch (Exception e) {
+ throw new RuntimeException("Could not start embedded ActiveMQ server", e);
+ }
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public void stop() {
+ try {
+ embedded.stop();
+ } catch (Exception e) {
+ throw new RuntimeException("Could not stop embedded ActiveMQ server", e);
+ }
+ }
+}
diff --git a/integration-tests/artemis-core/src/test/resources/broker.xml b/integration-tests/artemis-core/src/test/resources/broker.xml
new file mode 100644
index 0000000000000..ebc7ccd91575d
--- /dev/null
+++ b/integration-tests/artemis-core/src/test/resources/broker.xml
@@ -0,0 +1,25 @@
+
+
+ ./target/artemis/paging
+ ./target/artemis/bindings
+ ./target/artemis/journal
+ ./target/artemis/large-messages
+
+
+ tcp://localhost:61616
+
+
+ tcp://localhost:61616
+
+
+ false
+
+
+
+
+
+
+
+
+
+
diff --git a/integration-tests/artemis-jms/pom.xml b/integration-tests/artemis-jms/pom.xml
new file mode 100644
index 0000000000000..54483c49c58c1
--- /dev/null
+++ b/integration-tests/artemis-jms/pom.xml
@@ -0,0 +1,127 @@
+
+
+
+ quarkus-integration-tests-parent
+ io.quarkus
+ 999-SNAPSHOT
+
+ 4.0.0
+
+ quarkus-integration-test-artemis-jms
+ Quarkus - Integration Tests - Artemis - JMS
+ The Apache ActiveMQ Artemis JMS integration tests module
+
+
+ true
+
+
+
+
+
+ io.quarkus
+ quarkus-resteasy
+
+
+
+
+ io.quarkus
+ quarkus-artemis-jms
+
+
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+ io.rest-assured
+ rest-assured
+ test
+
+
+ org.apache.activemq
+ artemis-server
+ ${artemis.version}
+ test
+
+
+ org.jboss.logmanager
+ jboss-logmanager
+
+
+
+
+
+
+
+
+ ${project.groupId}
+ quarkus-maven-plugin
+
+
+
+ build
+
+
+
+
+
+
+
+
+
+ native-image
+
+
+ native
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ integration-test
+ verify
+
+
+
+ ${project.build.directory}/${project.build.finalName}-runner
+
+
+
+
+
+
+ ${project.groupId}
+ quarkus-maven-plugin
+
+
+ native-image
+
+ native-image
+
+
+ true
+ true
+
+ ${graalvmHome}
+
+
+
+
+
+
+
+
+
+
diff --git a/integration-tests/artemis-jms/src/main/java/io/quarkus/it/artemis/ArtemisConsumerManager.java b/integration-tests/artemis-jms/src/main/java/io/quarkus/it/artemis/ArtemisConsumerManager.java
new file mode 100644
index 0000000000000..5452a493cd0a7
--- /dev/null
+++ b/integration-tests/artemis-jms/src/main/java/io/quarkus/it/artemis/ArtemisConsumerManager.java
@@ -0,0 +1,34 @@
+package io.quarkus.it.artemis;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.MessageConsumer;
+import javax.jms.Session;
+
+@ApplicationScoped
+public class ArtemisConsumerManager {
+
+ @Inject
+ ConnectionFactory connectionFactory;
+
+ private Connection connection;
+
+ @PostConstruct
+ public void init() throws JMSException {
+ connection = connectionFactory.createConnection();
+ connection.start();
+ }
+
+ public String receive() {
+ try (Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) {
+ MessageConsumer consumer = session.createConsumer(session.createQueue("test-jms"));
+ return consumer.receive(1000L).getBody(String.class);
+ } catch (JMSException e) {
+ throw new RuntimeException("Could not receive message", e);
+ }
+ }
+}
diff --git a/integration-tests/artemis-jms/src/main/java/io/quarkus/it/artemis/ArtemisEndpoint.java b/integration-tests/artemis-jms/src/main/java/io/quarkus/it/artemis/ArtemisEndpoint.java
new file mode 100644
index 0000000000000..09fcc62d76fd6
--- /dev/null
+++ b/integration-tests/artemis-jms/src/main/java/io/quarkus/it/artemis/ArtemisEndpoint.java
@@ -0,0 +1,26 @@
+package io.quarkus.it.artemis;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+@Path("/artemis")
+public class ArtemisEndpoint {
+
+ @Inject
+ ArtemisProducerManager producer;
+
+ @Inject
+ ArtemisConsumerManager consumer;
+
+ @POST
+ public void post(String message) {
+ producer.send(message);
+ }
+
+ @GET
+ public String get() {
+ return consumer.receive();
+ }
+}
diff --git a/integration-tests/artemis-jms/src/main/java/io/quarkus/it/artemis/ArtemisProducerManager.java b/integration-tests/artemis-jms/src/main/java/io/quarkus/it/artemis/ArtemisProducerManager.java
new file mode 100644
index 0000000000000..edd8016e1030c
--- /dev/null
+++ b/integration-tests/artemis-jms/src/main/java/io/quarkus/it/artemis/ArtemisProducerManager.java
@@ -0,0 +1,33 @@
+package io.quarkus.it.artemis;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+
+@ApplicationScoped
+public class ArtemisProducerManager {
+
+ @Inject
+ ConnectionFactory connectionFactory;
+
+ private Connection connection;
+
+ @PostConstruct
+ public void init() throws JMSException {
+ connection = connectionFactory.createConnection();
+ }
+
+ public void send(String body) {
+ try (Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) {
+ MessageProducer producer = session.createProducer(session.createQueue("test-jms"));
+ producer.send(session.createTextMessage(body));
+ } catch (JMSException e) {
+ throw new RuntimeException("Could not send message", e);
+ }
+ }
+}
diff --git a/integration-tests/artemis-jms/src/main/resources/application.properties b/integration-tests/artemis-jms/src/main/resources/application.properties
new file mode 100644
index 0000000000000..d7f1552f7a3ae
--- /dev/null
+++ b/integration-tests/artemis-jms/src/main/resources/application.properties
@@ -0,0 +1 @@
+quarkus.artemis.url=tcp://localhost:61616
diff --git a/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisConsumerITCase.java b/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisConsumerITCase.java
new file mode 100644
index 0000000000000..062348efe2579
--- /dev/null
+++ b/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisConsumerITCase.java
@@ -0,0 +1,8 @@
+package io.quarkus.it.artemis;
+
+import io.quarkus.test.junit.SubstrateTest;
+
+@SubstrateTest
+public class ArtemisConsumerITCase extends ArtemisConsumerTest {
+
+}
diff --git a/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisConsumerTest.java b/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisConsumerTest.java
new file mode 100644
index 0000000000000..d7e6aee554a2b
--- /dev/null
+++ b/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisConsumerTest.java
@@ -0,0 +1,29 @@
+package io.quarkus.it.artemis;
+
+import javax.jms.Session;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import io.restassured.response.Response;
+import io.undertow.httpcore.StatusCodes;
+
+@QuarkusTest
+@QuarkusTestResource(ArtemisTestResource.class)
+public class ArtemisConsumerTest implements ArtemisHelper {
+
+ @Test
+ public void test() throws Exception {
+ String body = createBody();
+ try (Session session = createSession()) {
+ session.createProducer(session.createQueue("test-jms")).send(session.createTextMessage(body));
+ }
+
+ Response response = RestAssured.with().body(body).get("/artemis");
+ Assertions.assertEquals(StatusCodes.OK, response.statusCode());
+ Assertions.assertEquals(body, response.getBody().asString());
+ }
+}
diff --git a/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisHelper.java b/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisHelper.java
new file mode 100644
index 0000000000000..33dd8511cb72f
--- /dev/null
+++ b/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisHelper.java
@@ -0,0 +1,22 @@
+package io.quarkus.it.artemis;
+
+import java.util.Random;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.Session;
+
+import org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory;
+
+public interface ArtemisHelper {
+
+ default String createBody() {
+ return Integer.toString(new Random().nextInt(Integer.MAX_VALUE), 16);
+ }
+
+ default Session createSession() throws JMSException {
+ Connection connection = new ActiveMQJMSConnectionFactory("tcp://localhost:61616").createConnection();
+ connection.start();
+ return connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ }
+}
diff --git a/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisProducerITCase.java b/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisProducerITCase.java
new file mode 100644
index 0000000000000..d8aea4c888df5
--- /dev/null
+++ b/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisProducerITCase.java
@@ -0,0 +1,8 @@
+package io.quarkus.it.artemis;
+
+import io.quarkus.test.junit.SubstrateTest;
+
+@SubstrateTest
+public class ArtemisProducerITCase extends ArtemisProducerTest {
+
+}
diff --git a/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisProducerTest.java b/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisProducerTest.java
new file mode 100644
index 0000000000000..11238b6bc4107
--- /dev/null
+++ b/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisProducerTest.java
@@ -0,0 +1,32 @@
+package io.quarkus.it.artemis;
+
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.Session;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import io.restassured.response.Response;
+import io.undertow.httpcore.StatusCodes;
+
+@QuarkusTest
+@QuarkusTestResource(ArtemisTestResource.class)
+public class ArtemisProducerTest implements ArtemisHelper {
+
+ @Test
+ public void test() throws Exception {
+ String body = createBody();
+ Response response = RestAssured.with().body(body).post("/artemis");
+ Assertions.assertEquals(StatusCodes.NO_CONTENT, response.statusCode());
+
+ try (Session session = createSession()) {
+ MessageConsumer consumer = session.createConsumer(session.createQueue("test-jms"));
+ Message message = consumer.receive(1000L);
+ Assertions.assertEquals(body, message.getBody(String.class));
+ }
+ }
+}
diff --git a/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisTestResource.java b/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisTestResource.java
new file mode 100644
index 0000000000000..581cde9b6f67d
--- /dev/null
+++ b/integration-tests/artemis-jms/src/test/java/io/quarkus/it/artemis/ArtemisTestResource.java
@@ -0,0 +1,36 @@
+package io.quarkus.it.artemis;
+
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
+import org.apache.commons.io.FileUtils;
+
+import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
+
+public class ArtemisTestResource implements QuarkusTestResourceLifecycleManager {
+
+ private EmbeddedActiveMQ embedded;
+
+ @Override
+ public Map start() {
+ try {
+ FileUtils.deleteDirectory(Paths.get("./target/artemis").toFile());
+ embedded = new EmbeddedActiveMQ();
+ embedded.start();
+ } catch (Exception e) {
+ throw new RuntimeException("Could not start embedded ActiveMQ server", e);
+ }
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public void stop() {
+ try {
+ embedded.stop();
+ } catch (Exception e) {
+ throw new RuntimeException("Could not stop embedded ActiveMQ server", e);
+ }
+ }
+}
diff --git a/integration-tests/artemis-jms/src/test/resources/broker.xml b/integration-tests/artemis-jms/src/test/resources/broker.xml
new file mode 100644
index 0000000000000..b3e4ec0d49861
--- /dev/null
+++ b/integration-tests/artemis-jms/src/test/resources/broker.xml
@@ -0,0 +1,23 @@
+
+
+ ./target/artemis/paging
+ ./target/artemis/bindings
+ ./target/artemis/journal
+ ./target/artemis/large-messages
+
+
+ tcp://localhost:61616
+
+
+ tcp://localhost:61616
+
+
+ false
+
+
+
+ test-jms
+
+
+
+
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index dc81db73ae607..840f9c654eaf7 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -54,6 +54,8 @@
resteasy-jackson
jgit
virtual-http
+ artemis-core
+ artemis-jms