diff --git a/extension/runtime/src/main/java/io/quarkiverse/temporal/config/ConnectionRuntimeConfig.java b/extension/runtime/src/main/java/io/quarkiverse/temporal/config/ConnectionRuntimeConfig.java
index 07282aa..eb93cb9 100644
--- a/extension/runtime/src/main/java/io/quarkiverse/temporal/config/ConnectionRuntimeConfig.java
+++ b/extension/runtime/src/main/java/io/quarkiverse/temporal/config/ConnectionRuntimeConfig.java
@@ -11,9 +11,8 @@ public interface ConnectionRuntimeConfig {
/**
* Sets a target string, which can be either a valid {@link NameResolver}-compliant URI, or an
* authority string. See {@link ManagedChannelBuilder#forTarget(String)} for more information
- * about parameter format. Default is 127.0.0.1:7233
+ * about parameter format.
*/
- @WithDefault("127.0.0.1:7233")
String target();
/**
diff --git a/extension/runtime/src/main/java/io/quarkiverse/temporal/config/TemporalBuildtimeConfig.java b/extension/runtime/src/main/java/io/quarkiverse/temporal/config/TemporalBuildtimeConfig.java
index 7b01a40..b538059 100644
--- a/extension/runtime/src/main/java/io/quarkiverse/temporal/config/TemporalBuildtimeConfig.java
+++ b/extension/runtime/src/main/java/io/quarkiverse/temporal/config/TemporalBuildtimeConfig.java
@@ -21,7 +21,10 @@ enum ChannelType {
}
/**
- * enable mock for testing
+ * enable mock for testing.
+ *
+ *
+ * If enabled, the Temporal devservice will not be started.
*/
@WithDefault("false")
Boolean enableMock();
diff --git a/extension/runtime/src/main/java/io/quarkiverse/temporal/devui/TemporalUiProxy.java b/extension/runtime/src/main/java/io/quarkiverse/temporal/devui/TemporalUiProxy.java
new file mode 100644
index 0000000..3b49ed1
--- /dev/null
+++ b/extension/runtime/src/main/java/io/quarkiverse/temporal/devui/TemporalUiProxy.java
@@ -0,0 +1,74 @@
+package io.quarkiverse.temporal.devui;
+
+import java.net.URL;
+import java.util.Optional;
+import java.util.function.Supplier;
+
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.jboss.logging.Logger;
+
+import io.quarkus.runtime.annotations.Recorder;
+import io.vertx.core.Handler;
+import io.vertx.core.Vertx;
+import io.vertx.core.buffer.Buffer;
+import io.vertx.ext.web.RoutingContext;
+import io.vertx.ext.web.client.HttpRequest;
+import io.vertx.ext.web.client.WebClient;
+
+@Recorder
+public class TemporalUiProxy {
+
+ private static final Logger log = Logger.getLogger(TemporalUiProxy.class);
+
+ public Handler handler(Supplier vertx) {
+ final Optional urlOptional = ConfigProvider.getConfig().getOptionalValue("quarkus.temporal.ui.url",
+ String.class);
+ final var client = WebClient.create(vertx.get());
+
+ return new Handler() {
+ @Override
+ public void handle(RoutingContext event) {
+ if (!urlOptional.isPresent()) {
+ event.response().setStatusCode(404).end();
+ return;
+ }
+
+ URL url;
+ try {
+ url = new URL(urlOptional.get());
+ } catch (Exception e) {
+ log.error("Invalid URL: " + urlOptional.get(), e);
+ event.response().setStatusCode(500).end();
+ return;
+ }
+
+ final HttpRequest r = client.request(event.request().method(), url.getPort(), url.getHost(),
+ event.request().uri());
+
+ // copy all headers
+ event.request().headers().forEach(h -> r.putHeader(h.getKey(), h.getValue()));
+
+ if ("websocket".equals(event.request().getHeader("upgrade"))) {
+ // handle WebSocket request
+ event.request().toWebSocket().onComplete(ws -> {
+ if (ws.succeeded()) {
+ event.request().resume();
+ ws.result().handler(buff -> {
+ event.response().write(buff);
+ });
+ } else {
+ log.error("WebSocket failed", ws.cause());
+ }
+ });
+ } else {
+ // handle normal request
+ r.sendBuffer(event.body().buffer()).andThen(resp -> {
+ event.response().setStatusCode(resp.result().statusCode());
+ resp.result().headers().forEach(h -> event.response().putHeader(h.getKey(), h.getValue()));
+ event.response().end(resp.result().bodyAsBuffer());
+ });
+ }
+ }
+ };
+ }
+}
diff --git a/integration-tests/devservice/pom.xml b/integration-tests/devservice/pom.xml
new file mode 100644
index 0000000..ab3328f
--- /dev/null
+++ b/integration-tests/devservice/pom.xml
@@ -0,0 +1,141 @@
+
+
+ 4.0.0
+
+ io.quarkiverse.temporal
+ quarkus-temporal-parent
+ 999-SNAPSHOT
+ ../../pom.xml
+
+ quarkus-temporal-integration-tests-devservice
+ Temporal - Integration Tests - Devservice
+
+ true
+
+
+
+ io.quarkus
+ quarkus-arc
+
+
+ io.quarkus
+ quarkus-grpc
+
+
+ io.quarkus
+ quarkus-info
+
+
+ io.quarkus
+ quarkus-resteasy-jackson
+
+
+ io.quarkus
+ quarkus-smallrye-openapi
+
+
+ io.quarkus
+ quarkus-smallrye-health
+
+
+ io.quarkus
+ quarkus-opentelemetry
+
+
+ io.quarkus
+ quarkus-micrometer-registry-prometheus
+
+
+ io.quarkiverse.temporal
+ quarkus-temporal
+ ${project.version}
+
+
+ org.apache.commons
+ commons-lang3
+
+
+ io.quarkiverse.temporal
+ quarkus-temporal-deployment
+ ${project.version}
+
+
+ *
+ *
+
+
+
+
+ io.quarkus
+ quarkus-devservices-deployment
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+ io.rest-assured
+ rest-assured
+ test
+
+
+
+
+
+
+ io.quarkus
+ quarkus-maven-plugin
+
+
+
+ build
+
+
+
+
+
+ maven-failsafe-plugin
+
+
+
+ integration-test
+ verify
+
+
+
+
+
+ ${project.build.directory}/${project.build.finalName}-runner
+ org.jboss.logmanager.LogManager
+ ${maven.home}
+
+
+
+
+
+
+
+ native-image
+
+
+ native
+
+
+
+
+
+ maven-surefire-plugin
+
+ ${native.surefire.skip}
+
+
+
+
+
+ false
+ true
+
+
+
+
\ No newline at end of file
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/cdi/CdiBean.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/cdi/CdiBean.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/cdi/CdiBean.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/cdi/CdiBean.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/cdi/defaultWorker/CDIActivityImpl.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/cdi/defaultWorker/CDIActivityImpl.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/cdi/defaultWorker/CDIActivityImpl.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/cdi/defaultWorker/CDIActivityImpl.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/cdi/defaultWorker/CDIWorkflowImpl.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/cdi/defaultWorker/CDIWorkflowImpl.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/cdi/defaultWorker/CDIWorkflowImpl.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/cdi/defaultWorker/CDIWorkflowImpl.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/cdi/namedWorker/CDIActivityImpl.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/cdi/namedWorker/CDIActivityImpl.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/cdi/namedWorker/CDIActivityImpl.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/cdi/namedWorker/CDIActivityImpl.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/cdi/namedWorker/CDIWorkflowImpl.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/cdi/namedWorker/CDIWorkflowImpl.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/cdi/namedWorker/CDIWorkflowImpl.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/cdi/namedWorker/CDIWorkflowImpl.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/cdi/shared/CDIActivity.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/cdi/shared/CDIActivity.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/cdi/shared/CDIActivity.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/cdi/shared/CDIActivity.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/cdi/shared/CDIWorkflow.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/cdi/shared/CDIWorkflow.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/cdi/shared/CDIWorkflow.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/cdi/shared/CDIWorkflow.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/AccountActivityImpl.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/AccountActivityImpl.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/AccountActivityImpl.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/AccountActivityImpl.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/CoreTransactionDetails.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/CoreTransactionDetails.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/CoreTransactionDetails.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/CoreTransactionDetails.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/MoneyTransferWorkflowImpl.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/MoneyTransferWorkflowImpl.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/MoneyTransferWorkflowImpl.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/MoneyTransferWorkflowImpl.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/AccountActivityImpl.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/AccountActivityImpl.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/AccountActivityImpl.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/AccountActivityImpl.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/CoreTransactionDetails.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/CoreTransactionDetails.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/CoreTransactionDetails.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/CoreTransactionDetails.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/MoneyTransferWorkflowImpl.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/MoneyTransferWorkflowImpl.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/MoneyTransferWorkflowImpl.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/MoneyTransferWorkflowImpl.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/AccountActivity.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/AccountActivity.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/AccountActivity.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/AccountActivity.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/MoneyTransferWorkflow.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/MoneyTransferWorkflow.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/MoneyTransferWorkflow.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/MoneyTransferWorkflow.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/TransactionDetails.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/TransactionDetails.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/TransactionDetails.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/TransactionDetails.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/rest/MoneyTransferResource.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/rest/MoneyTransferResource.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/rest/MoneyTransferResource.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/rest/MoneyTransferResource.java
diff --git a/integration-tests/src/main/java/io/quarkiverse/temporal/it/util/MDCContextPropagator.java b/integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/util/MDCContextPropagator.java
similarity index 100%
rename from integration-tests/src/main/java/io/quarkiverse/temporal/it/util/MDCContextPropagator.java
rename to integration-tests/devservice/src/main/java/io/quarkiverse/temporal/it/util/MDCContextPropagator.java
diff --git a/integration-tests/devservice/src/main/resources/application.properties b/integration-tests/devservice/src/main/resources/application.properties
new file mode 100644
index 0000000..e69de29
diff --git a/integration-tests/src/test/java/io/quarkiverse/temporal/it/CDIActivityIT.java b/integration-tests/devservice/src/test/java/io/quarkiverse/temporal/it/CDIActivityIT.java
similarity index 100%
rename from integration-tests/src/test/java/io/quarkiverse/temporal/it/CDIActivityIT.java
rename to integration-tests/devservice/src/test/java/io/quarkiverse/temporal/it/CDIActivityIT.java
diff --git a/integration-tests/src/test/java/io/quarkiverse/temporal/it/MoneyTransferIT.java b/integration-tests/devservice/src/test/java/io/quarkiverse/temporal/it/MoneyTransferIT.java
similarity index 100%
rename from integration-tests/src/test/java/io/quarkiverse/temporal/it/MoneyTransferIT.java
rename to integration-tests/devservice/src/test/java/io/quarkiverse/temporal/it/MoneyTransferIT.java
diff --git a/integration-tests/mock/pom.xml b/integration-tests/mock/pom.xml
new file mode 100644
index 0000000..3bfa0a3
--- /dev/null
+++ b/integration-tests/mock/pom.xml
@@ -0,0 +1,143 @@
+
+
+ 4.0.0
+
+ io.quarkiverse.temporal
+ quarkus-temporal-parent
+ 999-SNAPSHOT
+ ../../pom.xml
+
+ quarkus-temporal-integration-tests-mock
+ Temporal - Integration Tests - Mock
+
+ true
+
+
+
+ io.quarkus
+ quarkus-arc
+
+
+ io.quarkus
+ quarkus-grpc
+
+
+ io.quarkus
+ quarkus-info
+
+
+ io.quarkus
+ quarkus-resteasy-jackson
+
+
+ io.quarkus
+ quarkus-smallrye-openapi
+
+
+ io.quarkus
+ quarkus-smallrye-health
+
+
+ io.quarkus
+ quarkus-opentelemetry
+
+
+ io.quarkus
+ quarkus-micrometer-registry-prometheus
+
+
+ io.quarkiverse.temporal
+ quarkus-temporal
+ ${project.version}
+
+
+ io.quarkiverse.temporal
+ quarkus-temporal-test
+ ${project.version}
+ test
+
+
+ io.quarkiverse.temporal
+ quarkus-temporal-test-deployment
+ ${project.version}
+
+
+ io.quarkiverse.temporal
+ quarkus-temporal-deployment
+ ${project.version}
+
+
+ *
+ *
+
+
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+ io.rest-assured
+ rest-assured
+ test
+
+
+
+
+
+ io.quarkus
+ quarkus-maven-plugin
+
+
+
+ build
+
+
+
+
+
+ maven-failsafe-plugin
+
+
+
+ integration-test
+ verify
+
+
+
+
+
+ ${project.build.directory}/${project.build.finalName}-runner
+ org.jboss.logmanager.LogManager
+ ${maven.home}
+
+
+
+
+
+
+
+ native-image
+
+
+ native
+
+
+
+
+
+ maven-surefire-plugin
+
+ ${native.surefire.skip}
+
+
+
+
+
+ false
+ true
+
+
+
+
\ No newline at end of file
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/CdiBean.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/CdiBean.java
new file mode 100644
index 0000000..1740109
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/CdiBean.java
@@ -0,0 +1,12 @@
+package io.quarkiverse.temporal.it.cdi;
+
+import jakarta.enterprise.context.ApplicationScoped;
+
+@ApplicationScoped
+public class CdiBean {
+
+ public void someMethod() {
+ System.out.println("Calling CDI Bean from Activity");
+ System.out.flush();
+ }
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/defaultWorker/CDIActivityImpl.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/defaultWorker/CDIActivityImpl.java
new file mode 100644
index 0000000..6e454a6
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/defaultWorker/CDIActivityImpl.java
@@ -0,0 +1,18 @@
+package io.quarkiverse.temporal.it.cdi.defaultWorker;
+
+import jakarta.inject.Inject;
+
+import io.quarkiverse.temporal.it.cdi.CdiBean;
+import io.quarkiverse.temporal.it.cdi.shared.CDIActivity;
+
+public class CDIActivityImpl implements CDIActivity {
+
+ @Inject
+ CdiBean cdiBean;
+
+ @Override
+ public void cdi() {
+ cdiBean.someMethod();
+
+ }
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/defaultWorker/CDIWorkflowImpl.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/defaultWorker/CDIWorkflowImpl.java
new file mode 100644
index 0000000..e8b8e68
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/defaultWorker/CDIWorkflowImpl.java
@@ -0,0 +1,36 @@
+package io.quarkiverse.temporal.it.cdi.defaultWorker;
+
+import java.time.Duration;
+
+import io.quarkiverse.temporal.it.cdi.shared.CDIActivity;
+import io.quarkiverse.temporal.it.cdi.shared.CDIWorkflow;
+import io.temporal.activity.ActivityOptions;
+import io.temporal.common.RetryOptions;
+import io.temporal.workflow.Workflow;
+
+public class CDIWorkflowImpl implements CDIWorkflow {
+
+ // RetryOptions specify how to automatically handle retries when Activities fail
+ private final RetryOptions retryoptions = RetryOptions.newBuilder()
+ .setInitialInterval(Duration.ofSeconds(1)) // Wait 1 second before first retry
+ .setMaximumInterval(Duration.ofSeconds(20)) // Do not exceed 20 seconds between retries
+ .setBackoffCoefficient(2) // Wait 1 second, then 2, then 4, etc
+ .setMaximumAttempts(5000) // Fail after 5000 attempts
+ .build();
+
+ // ActivityOptions specify the limits on how long an Activity can execute before
+ // being interrupted by the Orchestration service
+ private final ActivityOptions defaultActivityOptions = ActivityOptions.newBuilder()
+ .setRetryOptions(retryoptions) // Apply the RetryOptions defined above
+ .setStartToCloseTimeout(Duration.ofSeconds(2)) // Max execution time for single Activity
+ .setScheduleToCloseTimeout(Duration.ofSeconds(5000)) // Entire duration from scheduling to completion including queue time
+ .build();
+
+ // ActivityStubs enable calls to methods as if the Activity object is local but actually perform an RPC invocation
+ private final CDIActivity cdiActivity = Workflow.newActivityStub(CDIActivity.class, defaultActivityOptions);
+
+ @Override
+ public void cdi() {
+ cdiActivity.cdi();
+ }
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/namedWorker/CDIActivityImpl.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/namedWorker/CDIActivityImpl.java
new file mode 100644
index 0000000..99fc763
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/namedWorker/CDIActivityImpl.java
@@ -0,0 +1,20 @@
+package io.quarkiverse.temporal.it.cdi.namedWorker;
+
+import jakarta.inject.Inject;
+
+import io.quarkiverse.temporal.TemporalActivity;
+import io.quarkiverse.temporal.it.cdi.CdiBean;
+import io.quarkiverse.temporal.it.cdi.shared.CDIActivity;
+
+@TemporalActivity(workers = "namedWorker")
+public class CDIActivityImpl implements CDIActivity {
+
+ @Inject
+ CdiBean cdiBean;
+
+ @Override
+ public void cdi() {
+ cdiBean.someMethod();
+
+ }
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/namedWorker/CDIWorkflowImpl.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/namedWorker/CDIWorkflowImpl.java
new file mode 100644
index 0000000..8a9d85e
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/namedWorker/CDIWorkflowImpl.java
@@ -0,0 +1,38 @@
+package io.quarkiverse.temporal.it.cdi.namedWorker;
+
+import java.time.Duration;
+
+import io.quarkiverse.temporal.TemporalWorkflow;
+import io.quarkiverse.temporal.it.cdi.shared.CDIActivity;
+import io.quarkiverse.temporal.it.cdi.shared.CDIWorkflow;
+import io.temporal.activity.ActivityOptions;
+import io.temporal.common.RetryOptions;
+import io.temporal.workflow.Workflow;
+
+@TemporalWorkflow(workers = "namedWorker")
+public class CDIWorkflowImpl implements CDIWorkflow {
+
+ // RetryOptions specify how to automatically handle retries when Activities fail
+ private final RetryOptions retryoptions = RetryOptions.newBuilder()
+ .setInitialInterval(Duration.ofSeconds(1)) // Wait 1 second before first retry
+ .setMaximumInterval(Duration.ofSeconds(20)) // Do not exceed 20 seconds between retries
+ .setBackoffCoefficient(2) // Wait 1 second, then 2, then 4, etc
+ .setMaximumAttempts(5000) // Fail after 5000 attempts
+ .build();
+
+ // ActivityOptions specify the limits on how long an Activity can execute before
+ // being interrupted by the Orchestration service
+ private final ActivityOptions defaultActivityOptions = ActivityOptions.newBuilder()
+ .setRetryOptions(retryoptions) // Apply the RetryOptions defined above
+ .setStartToCloseTimeout(Duration.ofSeconds(2)) // Max execution time for single Activity
+ .setScheduleToCloseTimeout(Duration.ofSeconds(5000)) // Entire duration from scheduling to completion including queue time
+ .build();
+
+ // ActivityStubs enable calls to methods as if the Activity object is local but actually perform an RPC invocation
+ private final CDIActivity cdiActivity = Workflow.newActivityStub(CDIActivity.class, defaultActivityOptions);
+
+ @Override
+ public void cdi() {
+ cdiActivity.cdi();
+ }
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/shared/CDIActivity.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/shared/CDIActivity.java
new file mode 100644
index 0000000..5e7fbba
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/shared/CDIActivity.java
@@ -0,0 +1,12 @@
+package io.quarkiverse.temporal.it.cdi.shared;
+
+import io.temporal.activity.ActivityInterface;
+import io.temporal.activity.ActivityMethod;
+
+@ActivityInterface
+public interface CDIActivity {
+
+ @ActivityMethod
+ void cdi();
+
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/shared/CDIWorkflow.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/shared/CDIWorkflow.java
new file mode 100644
index 0000000..e8cf8bd
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/cdi/shared/CDIWorkflow.java
@@ -0,0 +1,11 @@
+package io.quarkiverse.temporal.it.cdi.shared;
+
+import io.temporal.workflow.WorkflowInterface;
+import io.temporal.workflow.WorkflowMethod;
+
+@WorkflowInterface
+public interface CDIWorkflow {
+
+ @WorkflowMethod
+ void cdi();
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/AccountActivityImpl.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/AccountActivityImpl.java
new file mode 100644
index 0000000..4bf40e3
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/AccountActivityImpl.java
@@ -0,0 +1,43 @@
+package io.quarkiverse.temporal.it.moneyTransfer.defaultWorker;
+
+import io.quarkiverse.temporal.it.moneyTransfer.shared.AccountActivity;
+import io.temporal.activity.Activity;
+
+public class AccountActivityImpl implements AccountActivity {
+
+ // Mock up the withdrawal of an amount of money from the source account
+ @Override
+ public void withdraw(String accountId, String referenceId, int amount) {
+ System.out.printf("\nWithdrawing $%d from account %s.\n[ReferenceId: %s]\n", amount, accountId, referenceId);
+ System.out.flush();
+ }
+
+ // Mock up the deposit of an amount of money from the destination account
+ @Override
+ public void deposit(String accountId, String referenceId, int amount) {
+ boolean activityShouldSucceed = true;
+ if (!activityShouldSucceed) {
+ System.out.println("Deposit failed");
+ System.out.flush();
+ throw Activity.wrap(new RuntimeException("Simulated Activity error during deposit of funds"));
+ }
+
+ System.out.printf("\nDepositing $%d into account %s.\n[ReferenceId: %s]\n", amount, accountId, referenceId);
+ System.out.flush();
+ }
+
+ // Mock up a compensation refund to the source account
+ @Override
+ public void refund(String accountId, String referenceId, int amount) {
+ boolean activityShouldSucceed = true;
+
+ if (!activityShouldSucceed) {
+ System.out.println("Refund failed");
+ System.out.flush();
+ throw Activity.wrap(new RuntimeException("Simulated Activity error during refund to source account"));
+ }
+
+ System.out.printf("\nRefunding $%d to account %s.\n[ReferenceId: %s]\n", amount, accountId, referenceId);
+ System.out.flush();
+ }
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/CoreTransactionDetails.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/CoreTransactionDetails.java
new file mode 100644
index 0000000..2fbacc4
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/CoreTransactionDetails.java
@@ -0,0 +1,43 @@
+package io.quarkiverse.temporal.it.moneyTransfer.defaultWorker;
+
+import io.quarkiverse.temporal.it.moneyTransfer.shared.TransactionDetails;
+
+public class CoreTransactionDetails implements TransactionDetails {
+
+ private String sourceAccountId;
+ private String destinationAccountId;
+ private String transactionReferenceId;
+ private int amountToTransfer;
+
+ public CoreTransactionDetails() {
+ // Default constructor is needed for Jackson deserialization
+ }
+
+ public CoreTransactionDetails(String sourceAccountId,
+ String destinationAccountId,
+ String transactionReferenceId,
+ int amountToTransfer) {
+ this.sourceAccountId = sourceAccountId;
+ this.destinationAccountId = destinationAccountId;
+ this.transactionReferenceId = transactionReferenceId;
+ this.amountToTransfer = amountToTransfer;
+ }
+
+ // MARK: Getter methods
+
+ public String getSourceAccountId() {
+ return sourceAccountId;
+ }
+
+ public String getDestinationAccountId() {
+ return destinationAccountId;
+ }
+
+ public String getTransactionReferenceId() {
+ return transactionReferenceId;
+ }
+
+ public int getAmountToTransfer() {
+ return amountToTransfer;
+ }
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/MoneyTransferWorkflowImpl.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/MoneyTransferWorkflowImpl.java
new file mode 100644
index 0000000..c849795
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/defaultWorker/MoneyTransferWorkflowImpl.java
@@ -0,0 +1,115 @@
+package io.quarkiverse.temporal.it.moneyTransfer.defaultWorker;
+
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+
+import io.quarkiverse.temporal.it.moneyTransfer.shared.AccountActivity;
+import io.quarkiverse.temporal.it.moneyTransfer.shared.MoneyTransferWorkflow;
+import io.quarkiverse.temporal.it.moneyTransfer.shared.TransactionDetails;
+import io.temporal.activity.ActivityOptions;
+import io.temporal.common.RetryOptions;
+import io.temporal.workflow.Workflow;
+
+public class MoneyTransferWorkflowImpl implements MoneyTransferWorkflow {
+ private static final String WITHDRAW = "Withdraw";
+
+ // RetryOptions specify how to automatically handle retries when Activities fail
+ private final RetryOptions retryoptions = RetryOptions.newBuilder()
+ .setInitialInterval(Duration.ofSeconds(1)) // Wait 1 second before first retry
+ .setMaximumInterval(Duration.ofSeconds(20)) // Do not exceed 20 seconds between retries
+ .setBackoffCoefficient(2) // Wait 1 second, then 2, then 4, etc
+ .setMaximumAttempts(5000) // Fail after 5000 attempts
+ .build();
+
+ // ActivityOptions specify the limits on how long an Activity can execute before
+ // being interrupted by the Orchestration service
+ private final ActivityOptions defaultActivityOptions = ActivityOptions.newBuilder()
+ .setRetryOptions(retryoptions) // Apply the RetryOptions defined above
+ .setStartToCloseTimeout(Duration.ofSeconds(2)) // Max execution time for single Activity
+ .setScheduleToCloseTimeout(Duration.ofSeconds(5000)) // Entire duration from scheduling to completion including queue time
+ .build();
+
+ private final Map perActivityMethodOptions = new HashMap() {
+ {
+ // A heartbeat time-out is a proof-of life indicator that an activity is still working.
+ // The 5 second duration used here waits for up to 5 seconds to hear a heartbeat.
+ // If one is not heard, the Activity fails.
+ // The `withdraw` method is hard-coded to succeed, so this never happens.
+ // Use heartbeats for long-lived event-driven applications.
+ put(WITHDRAW, ActivityOptions.newBuilder().setHeartbeatTimeout(Duration.ofSeconds(5)).build());
+ }
+ };
+
+ // ActivityStubs enable calls to methods as if the Activity object is local but actually perform an RPC invocation
+ private final AccountActivity accountActivityStub = Workflow.newActivityStub(AccountActivity.class, defaultActivityOptions,
+ perActivityMethodOptions);
+
+ // The transfer method is the entry point to the Workflow
+ // Activity method executions can be orchestrated here or from within other Activity methods
+ @Override
+ public void transfer(TransactionDetails transaction) {
+ // Retrieve transaction information from the `transaction` instance
+ String sourceAccountId = transaction.getSourceAccountId();
+ String destinationAccountId = transaction.getDestinationAccountId();
+ String transactionReferenceId = transaction.getTransactionReferenceId();
+ int amountToTransfer = transaction.getAmountToTransfer();
+
+ // Stage 1: Withdraw funds from source
+ try {
+ // Launch `withdrawal` Activity
+ accountActivityStub.withdraw(sourceAccountId, transactionReferenceId, amountToTransfer);
+ } catch (Exception e) {
+ // If the withdrawal fails, for any exception, it's caught here
+ System.out.printf("[%s] Withdrawal of $%d from account %s failed", transactionReferenceId, amountToTransfer,
+ sourceAccountId);
+ System.out.flush();
+
+ // Transaction ends here
+ return;
+ }
+
+ // Stage 2: Deposit funds to destination
+ try {
+ // Perform `deposit` Activity
+ accountActivityStub.deposit(destinationAccountId, transactionReferenceId, amountToTransfer);
+
+ // The `deposit` was successful
+ System.out.printf("[%s] Transaction succeeded.\n", transactionReferenceId);
+ System.out.flush();
+
+ // Transaction ends here
+ return;
+ } catch (Exception e) {
+ // If the deposit fails, for any exception, it's caught here
+ System.out.printf("[%s] Deposit of $%d to account %s failed.\n", transactionReferenceId, amountToTransfer,
+ destinationAccountId);
+ System.out.flush();
+ }
+
+ // Continue by compensating with a refund
+
+ try {
+ // Perform `refund` Activity
+ System.out.printf("[%s] Refunding $%d to account %s.\n", transactionReferenceId, amountToTransfer, sourceAccountId);
+ System.out.flush();
+
+ accountActivityStub.refund(sourceAccountId, transactionReferenceId, amountToTransfer);
+
+ // Recovery successful. Transaction ends here
+ System.out.printf("[%s] Refund to originating account was successful.\n", transactionReferenceId);
+ System.out.printf("[%s] Transaction is complete. No transfer made.\n", transactionReferenceId);
+ return;
+ } catch (Exception e) {
+ // A recovery mechanism can fail too. Handle any exception here
+ System.out.printf("[%s] Deposit of $%d to account %s failed. Did not compensate withdrawal.\n",
+ transactionReferenceId, amountToTransfer, destinationAccountId);
+ System.out.printf("[%s] Workflow failed.", transactionReferenceId);
+ System.out.flush();
+
+ // Rethrowing the exception causes a Workflow Task failure
+ throw (e);
+ }
+ }
+
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/AccountActivityImpl.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/AccountActivityImpl.java
new file mode 100644
index 0000000..de7b201
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/AccountActivityImpl.java
@@ -0,0 +1,45 @@
+package io.quarkiverse.temporal.it.moneyTransfer.namedWorker;
+
+import io.quarkiverse.temporal.TemporalActivity;
+import io.quarkiverse.temporal.it.moneyTransfer.shared.AccountActivity;
+import io.temporal.activity.Activity;
+
+@TemporalActivity(workers = "namedWorker")
+public class AccountActivityImpl implements AccountActivity {
+
+ // Mock up the withdrawal of an amount of money from the source account
+ @Override
+ public void withdraw(String accountId, String referenceId, int amount) {
+ System.out.printf("\nWithdrawing $%d from account %s.\n[ReferenceId: %s]\n", amount, accountId, referenceId);
+ System.out.flush();
+ }
+
+ // Mock up the deposit of an amount of money from the destination account
+ @Override
+ public void deposit(String accountId, String referenceId, int amount) {
+ boolean activityShouldSucceed = true;
+ if (!activityShouldSucceed) {
+ System.out.println("Deposit failed");
+ System.out.flush();
+ throw Activity.wrap(new RuntimeException("Simulated Activity error during deposit of funds"));
+ }
+
+ System.out.printf("\nDepositing $%d into account %s.\n[ReferenceId: %s]\n", amount, accountId, referenceId);
+ System.out.flush();
+ }
+
+ // Mock up a compensation refund to the source account
+ @Override
+ public void refund(String accountId, String referenceId, int amount) {
+ boolean activityShouldSucceed = true;
+
+ if (!activityShouldSucceed) {
+ System.out.println("Refund failed");
+ System.out.flush();
+ throw Activity.wrap(new RuntimeException("Simulated Activity error during refund to source account"));
+ }
+
+ System.out.printf("\nRefunding $%d to account %s.\n[ReferenceId: %s]\n", amount, accountId, referenceId);
+ System.out.flush();
+ }
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/CoreTransactionDetails.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/CoreTransactionDetails.java
new file mode 100644
index 0000000..e3787aa
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/CoreTransactionDetails.java
@@ -0,0 +1,43 @@
+package io.quarkiverse.temporal.it.moneyTransfer.namedWorker;
+
+import io.quarkiverse.temporal.it.moneyTransfer.shared.TransactionDetails;
+
+public class CoreTransactionDetails implements TransactionDetails {
+
+ private String sourceAccountId;
+ private String destinationAccountId;
+ private String transactionReferenceId;
+ private int amountToTransfer;
+
+ public CoreTransactionDetails() {
+ // Default constructor is needed for Jackson deserialization
+ }
+
+ public CoreTransactionDetails(String sourceAccountId,
+ String destinationAccountId,
+ String transactionReferenceId,
+ int amountToTransfer) {
+ this.sourceAccountId = sourceAccountId;
+ this.destinationAccountId = destinationAccountId;
+ this.transactionReferenceId = transactionReferenceId;
+ this.amountToTransfer = amountToTransfer;
+ }
+
+ // MARK: Getter methods
+
+ public String getSourceAccountId() {
+ return sourceAccountId;
+ }
+
+ public String getDestinationAccountId() {
+ return destinationAccountId;
+ }
+
+ public String getTransactionReferenceId() {
+ return transactionReferenceId;
+ }
+
+ public int getAmountToTransfer() {
+ return amountToTransfer;
+ }
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/MoneyTransferWorkflowImpl.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/MoneyTransferWorkflowImpl.java
new file mode 100644
index 0000000..e77f0cc
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/namedWorker/MoneyTransferWorkflowImpl.java
@@ -0,0 +1,116 @@
+package io.quarkiverse.temporal.it.moneyTransfer.namedWorker;
+
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+
+import io.quarkiverse.temporal.TemporalWorkflow;
+import io.quarkiverse.temporal.it.moneyTransfer.shared.AccountActivity;
+import io.quarkiverse.temporal.it.moneyTransfer.shared.MoneyTransferWorkflow;
+import io.quarkiverse.temporal.it.moneyTransfer.shared.TransactionDetails;
+import io.temporal.activity.ActivityOptions;
+import io.temporal.common.RetryOptions;
+import io.temporal.workflow.Workflow;
+
+@TemporalWorkflow(workers = "namedWorker")
+public class MoneyTransferWorkflowImpl implements MoneyTransferWorkflow {
+ private static final String WITHDRAW = "Withdraw";
+
+ // RetryOptions specify how to automatically handle retries when Activities fail
+ private final RetryOptions retryoptions = RetryOptions.newBuilder()
+ .setInitialInterval(Duration.ofSeconds(1)) // Wait 1 second before first retry
+ .setMaximumInterval(Duration.ofSeconds(20)) // Do not exceed 20 seconds between retries
+ .setBackoffCoefficient(2) // Wait 1 second, then 2, then 4, etc
+ .setMaximumAttempts(5000) // Fail after 5000 attempts
+ .build();
+
+ // ActivityOptions specify the limits on how long an Activity can execute before
+ // being interrupted by the Orchestration service
+ private final ActivityOptions defaultActivityOptions = ActivityOptions.newBuilder()
+ .setRetryOptions(retryoptions) // Apply the RetryOptions defined above
+ .setStartToCloseTimeout(Duration.ofSeconds(2)) // Max execution time for single Activity
+ .setScheduleToCloseTimeout(Duration.ofSeconds(5000)) // Entire duration from scheduling to completion including queue time
+ .build();
+
+ private final Map perActivityMethodOptions = new HashMap() {
+ {
+ // A heartbeat time-out is a proof-of life indicator that an activity is still working.
+ // The 5 second duration used here waits for up to 5 seconds to hear a heartbeat.
+ // If one is not heard, the Activity fails.
+ // The `withdraw` method is hard-coded to succeed, so this never happens.
+ // Use heartbeats for long-lived event-driven applications.
+ put(WITHDRAW, ActivityOptions.newBuilder().setHeartbeatTimeout(Duration.ofSeconds(5)).build());
+ }
+ };
+
+ // ActivityStubs enable calls to methods as if the Activity object is local but actually perform an RPC invocation
+ private final AccountActivity accountActivityStub = Workflow.newActivityStub(AccountActivity.class, defaultActivityOptions,
+ perActivityMethodOptions);
+
+ // The transfer method is the entry point to the Workflow
+ // Activity method executions can be orchestrated here or from within other Activity methods
+ @Override
+ public void transfer(TransactionDetails transaction) {
+ // Retrieve transaction information from the `transaction` instance
+ String sourceAccountId = transaction.getSourceAccountId();
+ String destinationAccountId = transaction.getDestinationAccountId();
+ String transactionReferenceId = transaction.getTransactionReferenceId();
+ int amountToTransfer = transaction.getAmountToTransfer();
+
+ // Stage 1: Withdraw funds from source
+ try {
+ // Launch `withdrawal` Activity
+ accountActivityStub.withdraw(sourceAccountId, transactionReferenceId, amountToTransfer);
+ } catch (Exception e) {
+ // If the withdrawal fails, for any exception, it's caught here
+ System.out.printf("[%s] Withdrawal of $%d from account %s failed", transactionReferenceId, amountToTransfer,
+ sourceAccountId);
+ System.out.flush();
+
+ // Transaction ends here
+ return;
+ }
+
+ // Stage 2: Deposit funds to destination
+ try {
+ // Perform `deposit` Activity
+ accountActivityStub.deposit(destinationAccountId, transactionReferenceId, amountToTransfer);
+
+ // The `deposit` was successful
+ System.out.printf("[%s] Transaction succeeded.\n", transactionReferenceId);
+ System.out.flush();
+
+ // Transaction ends here
+ return;
+ } catch (Exception e) {
+ // If the deposit fails, for any exception, it's caught here
+ System.out.printf("[%s] Deposit of $%d to account %s failed.\n", transactionReferenceId, amountToTransfer,
+ destinationAccountId);
+ System.out.flush();
+ }
+
+ // Continue by compensating with a refund
+
+ try {
+ // Perform `refund` Activity
+ System.out.printf("[%s] Refunding $%d to account %s.\n", transactionReferenceId, amountToTransfer, sourceAccountId);
+ System.out.flush();
+
+ accountActivityStub.refund(sourceAccountId, transactionReferenceId, amountToTransfer);
+
+ // Recovery successful. Transaction ends here
+ System.out.printf("[%s] Refund to originating account was successful.\n", transactionReferenceId);
+ System.out.printf("[%s] Transaction is complete. No transfer made.\n", transactionReferenceId);
+ return;
+ } catch (Exception e) {
+ // A recovery mechanism can fail too. Handle any exception here
+ System.out.printf("[%s] Deposit of $%d to account %s failed. Did not compensate withdrawal.\n",
+ transactionReferenceId, amountToTransfer, destinationAccountId);
+ System.out.printf("[%s] Workflow failed.", transactionReferenceId);
+ System.out.flush();
+
+ // Rethrowing the exception causes a Workflow Task failure
+ throw (e);
+ }
+ }
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/AccountActivity.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/AccountActivity.java
new file mode 100644
index 0000000..aa9892e
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/AccountActivity.java
@@ -0,0 +1,20 @@
+package io.quarkiverse.temporal.it.moneyTransfer.shared;
+
+import io.temporal.activity.ActivityInterface;
+import io.temporal.activity.ActivityMethod;
+
+@ActivityInterface
+public interface AccountActivity {
+ // Withdraw an amount of money from the source account
+ @ActivityMethod
+ void withdraw(String accountId, String referenceId, int amount);
+
+ // Deposit an amount of money into the destination account
+ @ActivityMethod
+ void deposit(String accountId, String referenceId, int amount);
+
+ // Compensate a failed deposit by refunding to the original account
+ @ActivityMethod
+ void refund(String accountId, String referenceId, int amount);
+
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/MoneyTransferWorkflow.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/MoneyTransferWorkflow.java
new file mode 100644
index 0000000..fbb6a87
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/MoneyTransferWorkflow.java
@@ -0,0 +1,13 @@
+package io.quarkiverse.temporal.it.moneyTransfer.shared;
+
+import io.temporal.workflow.WorkflowInterface;
+import io.temporal.workflow.WorkflowMethod;
+
+@WorkflowInterface
+public interface MoneyTransferWorkflow {
+ // The Workflow Execution that starts this method can be initiated from code or
+ // from the 'temporal' CLI utility.
+ @WorkflowMethod
+ void transfer(TransactionDetails transaction);
+
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/TransactionDetails.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/TransactionDetails.java
new file mode 100644
index 0000000..8e53048
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/moneyTransfer/shared/TransactionDetails.java
@@ -0,0 +1,16 @@
+package io.quarkiverse.temporal.it.moneyTransfer.shared;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+import io.quarkiverse.temporal.it.moneyTransfer.defaultWorker.CoreTransactionDetails;
+
+@JsonDeserialize(as = CoreTransactionDetails.class)
+public interface TransactionDetails {
+ String getSourceAccountId();
+
+ String getDestinationAccountId();
+
+ String getTransactionReferenceId();
+
+ int getAmountToTransfer();
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/rest/MoneyTransferResource.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/rest/MoneyTransferResource.java
new file mode 100644
index 0000000..43d5a13
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/rest/MoneyTransferResource.java
@@ -0,0 +1,38 @@
+package io.quarkiverse.temporal.it.rest;
+
+import static io.quarkiverse.temporal.Constants.DEFAULT_WORKER_NAME;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+
+import io.quarkiverse.temporal.it.moneyTransfer.defaultWorker.CoreTransactionDetails;
+import io.quarkiverse.temporal.it.moneyTransfer.shared.MoneyTransferWorkflow;
+import io.quarkiverse.temporal.it.moneyTransfer.shared.TransactionDetails;
+import io.temporal.client.WorkflowClient;
+import io.temporal.client.WorkflowOptions;
+
+@Path("/money-transfer")
+public class MoneyTransferResource {
+
+ @Inject
+ WorkflowClient client;
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public TransactionDetails transferMoney(@QueryParam("sourceAccountId") String sourceAccountId,
+ @QueryParam("destinationAccountId") String destinationAccountId,
+ @QueryParam("transactionReferenceId") String transactionReferenceId,
+ @QueryParam("amountToTransfer") int amountToTransfer) {
+ WorkflowOptions options = WorkflowOptions.newBuilder()
+ .setTaskQueue(DEFAULT_WORKER_NAME)
+ .setWorkflowId("money-transfer-workflow")
+ .build();
+
+ MoneyTransferWorkflow workflow = client.newWorkflowStub(MoneyTransferWorkflow.class, options);
+ TransactionDetails transaction = new CoreTransactionDetails(sourceAccountId, destinationAccountId,
+ transactionReferenceId, amountToTransfer);
+ workflow.transfer(transaction);
+ return transaction;
+ }
+}
diff --git a/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/util/MDCContextPropagator.java b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/util/MDCContextPropagator.java
new file mode 100644
index 0000000..3ed717f
--- /dev/null
+++ b/integration-tests/mock/src/main/java/io/quarkiverse/temporal/it/util/MDCContextPropagator.java
@@ -0,0 +1,139 @@
+package io.quarkiverse.temporal.it.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import jakarta.inject.Singleton;
+
+import org.apache.commons.lang3.StringUtils;
+import org.jboss.logging.Logger;
+import org.slf4j.MDC;
+
+import com.google.protobuf.ByteString;
+
+import io.quarkus.arc.Unremovable;
+import io.temporal.api.common.v1.Payload;
+import io.temporal.common.context.ContextPropagator;
+import io.temporal.common.converter.GlobalDataConverter;
+
+/**
+ * A {@link ContextPropagator} implementation that propagates the SLF4J MDC
+ * (Mapped Diagnostic Context) across Temporal workflow and activity boundaries.
+ * This class ensures that MDC entries with keys starting with "X-" are
+ * propagated.
+ */
+@Singleton
+@Unremovable
+public class MDCContextPropagator implements ContextPropagator {
+
+ private static final Logger LOG = Logger.getLogger(MDCContextPropagator.class);
+
+ /**
+ * Gets the name of the context propagator.
+ *
+ * @return the name of the context propagator, which is the fully qualified
+ * class name.
+ */
+ @Override
+ public String getName() {
+ return this.getClass().getName();
+ }
+
+ /**
+ * Retrieves the current MDC context to be propagated.
+ *
+ * @return a map containing the current MDC context, filtered to include only
+ * entries with keys starting with "X-".
+ */
+ @Override
+ public Object getCurrentContext() {
+ Map context = new HashMap<>();
+ Map mdcContext = MDC.getCopyOfContextMap();
+ if (mdcContext != null) {
+ mdcContext.entrySet().stream()
+ .filter(entry -> entry.getKey().startsWith("X-"))
+ .forEach(entry -> context.put(entry.getKey(), entry.getValue()));
+ }
+ return context;
+ }
+
+ /**
+ * Sets the current MDC context from the given context map.
+ *
+ * @param context the context map containing MDC entries to be set.
+ */
+ @Override
+ public void setCurrentContext(Object context) {
+ if (context instanceof Map) {
+ @SuppressWarnings("unchecked")
+ Map contextMap = (Map) context;
+ contextMap.forEach(MDC::put);
+ }
+ }
+
+ /**
+ * Serializes the given context map to a map of Payloads.
+ *
+ * @param context the context map containing MDC entries to be serialized.
+ * @return a map of Payloads representing the serialized context.
+ */
+ @Override
+ public Map serializeContext(Object context) {
+ if (!(context instanceof Map)) {
+ return new HashMap<>();
+ }
+ @SuppressWarnings("unchecked")
+ Map contextMap = (Map) context;
+ Map serializedContext = new HashMap<>();
+ contextMap.forEach((key, value) -> GlobalDataConverter.get().toPayload(value)
+ .ifPresent(payload -> serializedContext.put(key, payload)));
+ return serializedContext;
+ }
+
+ /**
+ * Deserializes the given map of Payloads to a context map.
+ *
+ * @param context the map of Payloads to be deserialized.
+ * @return a context map containing the deserialized MDC entries.
+ */
+ @Override
+ public Object deserializeContext(Map context) {
+ Map contextMap = new HashMap<>();
+ context.forEach((key, payload) -> {
+
+ // Handle empty {} when the data value is empty
+ // Adding opentracing seems to add a new value with empty data
+ // and the dataconverter throws an error
+ // This actually might be a configuration error from earlier
+ // but leaving in right now
+ //
+ // {_tracer-data=metadata {
+ // key: "encoding"
+ // value: "json/plain"
+ // }
+ // data: "{}"
+ // }
+ try {
+ String payloadValue = StringUtils.EMPTY; // default value
+
+ // Convert data to string to compare
+ ByteString data = payload.getData();
+
+ // Check the value to see if it "empty"
+ if (data != null && !data.isEmpty()) {
+
+ // Check if the value isn't {}'s
+ if (!StringUtils.equals("{}", data.toStringUtf8())) {
+ payloadValue = GlobalDataConverter.get().fromPayload(payload, String.class, String.class);
+ }
+ }
+
+ // Add the value into the map
+ contextMap.put(key, payloadValue);
+ } catch (Exception e) {
+ LOG.warnf("Couldn't parse MDC Context Data Key %s", key);
+ }
+ });
+ return contextMap;
+ }
+}
\ No newline at end of file
diff --git a/integration-tests/mock/src/main/resources/application.properties b/integration-tests/mock/src/main/resources/application.properties
new file mode 100644
index 0000000..23c5d45
--- /dev/null
+++ b/integration-tests/mock/src/main/resources/application.properties
@@ -0,0 +1,2 @@
+quarkus.temporal.enable-mock=true
+quarkus.temporal.devservice.enabled=false
diff --git a/integration-tests/mock/src/test/java/io/quarkiverse/temporal/it/CDIActivityIT.java b/integration-tests/mock/src/test/java/io/quarkiverse/temporal/it/CDIActivityIT.java
new file mode 100644
index 0000000..dd533f3
--- /dev/null
+++ b/integration-tests/mock/src/test/java/io/quarkiverse/temporal/it/CDIActivityIT.java
@@ -0,0 +1,43 @@
+package io.quarkiverse.temporal.it;
+
+import static io.quarkiverse.temporal.Constants.DEFAULT_WORKER_NAME;
+
+import java.util.concurrent.TimeoutException;
+
+import jakarta.inject.Inject;
+
+import org.junit.jupiter.api.Test;
+
+import io.quarkiverse.temporal.it.cdi.shared.CDIWorkflow;
+import io.quarkus.test.junit.QuarkusTest;
+import io.temporal.client.WorkflowClient;
+import io.temporal.client.WorkflowOptions;
+
+@QuarkusTest
+public class CDIActivityIT {
+
+ @Inject
+ WorkflowClient client;
+
+ @Test
+ public void testCDIInActivityOnDefaultWorker() throws TimeoutException {
+ WorkflowOptions options = WorkflowOptions.newBuilder()
+ .setTaskQueue(DEFAULT_WORKER_NAME)
+ .setWorkflowId("cdi-workflow")
+ .build();
+
+ CDIWorkflow workflow = client.newWorkflowStub(CDIWorkflow.class, options);
+ workflow.cdi();
+ }
+
+ @Test
+ public void testCDIInActivityOnNamedWorker() throws TimeoutException {
+ WorkflowOptions options = WorkflowOptions.newBuilder()
+ .setTaskQueue("namedWorker")
+ .setWorkflowId("cdi-workflow")
+ .build();
+
+ CDIWorkflow workflow = client.newWorkflowStub(CDIWorkflow.class, options);
+ workflow.cdi();
+ }
+}
diff --git a/integration-tests/mock/src/test/java/io/quarkiverse/temporal/it/MoneyTransferIT.java b/integration-tests/mock/src/test/java/io/quarkiverse/temporal/it/MoneyTransferIT.java
new file mode 100644
index 0000000..7c24444
--- /dev/null
+++ b/integration-tests/mock/src/test/java/io/quarkiverse/temporal/it/MoneyTransferIT.java
@@ -0,0 +1,47 @@
+package io.quarkiverse.temporal.it;
+
+import static io.quarkiverse.temporal.Constants.DEFAULT_WORKER_NAME;
+
+import java.util.concurrent.TimeoutException;
+
+import jakarta.inject.Inject;
+
+import org.junit.jupiter.api.Test;
+
+import io.quarkiverse.temporal.it.moneyTransfer.defaultWorker.CoreTransactionDetails;
+import io.quarkiverse.temporal.it.moneyTransfer.shared.MoneyTransferWorkflow;
+import io.quarkiverse.temporal.it.moneyTransfer.shared.TransactionDetails;
+import io.quarkus.test.junit.QuarkusTest;
+import io.temporal.client.WorkflowClient;
+import io.temporal.client.WorkflowOptions;
+
+@QuarkusTest
+public class MoneyTransferIT {
+
+ @Inject
+ WorkflowClient client;
+
+ @Test
+ public void testRunWorkflowOnDefaultWorker() throws TimeoutException {
+ WorkflowOptions options = WorkflowOptions.newBuilder()
+ .setTaskQueue(DEFAULT_WORKER_NAME)
+ .setWorkflowId("money-transfer-workflow")
+ .build();
+
+ MoneyTransferWorkflow workflow = client.newWorkflowStub(MoneyTransferWorkflow.class, options);
+ TransactionDetails transaction = new CoreTransactionDetails("249020073", "152354872", "57c65dea-e57e-4a0a", 68);
+ workflow.transfer(transaction);
+ }
+
+ @Test
+ public void testRunWorkflowOnNamedWorker() throws TimeoutException {
+ WorkflowOptions options = WorkflowOptions.newBuilder()
+ .setTaskQueue("namedWorker")
+ .setWorkflowId("money-transfer-workflow")
+ .build();
+
+ MoneyTransferWorkflow workflow = client.newWorkflowStub(MoneyTransferWorkflow.class, options);
+ TransactionDetails transaction = new CoreTransactionDetails("249020073", "152354872", "57c65dea-e57e-4a0a", 68);
+ workflow.transfer(transaction);
+ }
+}
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index b64186e..4ccd2c5 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -1,146 +1,18 @@
-
+
4.0.0
io.quarkiverse.temporal
quarkus-temporal-parent
999-SNAPSHOT
- integration-tests
- Quarkus Temporal - Integration Tests
-
- true
-
-
-
- io.quarkus
- quarkus-arc
-
-
- io.quarkus
- quarkus-grpc
-
-
- io.quarkus
- quarkus-rest
-
-
- io.quarkus
- quarkus-rest-jackson
-
-
- io.quarkus
- quarkus-smallrye-openapi
-
-
- io.quarkus
- quarkus-smallrye-health
-
-
- io.quarkus
- quarkus-info
-
-
- io.quarkus
- quarkus-opentelemetry
-
-
- io.quarkus
- quarkus-micrometer-registry-prometheus
-
-
- io.quarkiverse.temporal
- quarkus-temporal
- ${project.version}
-
-
- io.quarkiverse.temporal
- quarkus-temporal-test
- ${project.version}
- test
-
-
- io.quarkiverse.temporal
- quarkus-temporal-test-deployment
- ${project.version}
-
-
- io.quarkiverse.temporal
- quarkus-temporal-deployment
- ${project.version}
-
-
- *
- *
-
-
-
-
- io.quarkus
- quarkus-junit5
- test
-
-
- io.rest-assured
- rest-assured
- test
-
-
-
-
-
- io.quarkus
- quarkus-maven-plugin
-
-
-
- build
-
-
-
-
-
- maven-failsafe-plugin
-
-
-
- integration-test
- verify
-
-
-
-
-
- ${project.build.directory}/${project.build.finalName}-runner
- org.jboss.logmanager.LogManager
- ${maven.home}
-
-
-
-
-
-
-
- native-image
-
-
- native
-
-
-
-
-
- maven-surefire-plugin
-
- ${native.surefire.skip}
-
-
-
-
-
- false
- true
-
-
-
+ quarkus-temporal-extension-integration-tests
+ Temporal - Integration Tests
+ pom
+
+
+ mock
+ devservice
+
+
\ No newline at end of file
diff --git a/integration-tests/src/main/resources/application.properties b/integration-tests/src/main/resources/application.properties
index cdd6159..ba37f2f 100644
--- a/integration-tests/src/main/resources/application.properties
+++ b/integration-tests/src/main/resources/application.properties
@@ -1,3 +1,3 @@
quarkus.http.port=8081
%test.quarkus.temporal.enable-mock=true
-quarkus.grpc.server.use-separate-server=false
\ No newline at end of file
+quarkus.grpc.server.use-separate-server=false
diff --git a/pom.xml b/pom.xml
index 8c2183d..d796539 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,6 @@
UTF-8
3.15.1
1.26.0
- 1.32.0