getPropertyNames() {
+ return CONFIG.keySet();
+ }
+
+ @Override
+ public int getOrdinal() {
+ return 5000;
+ }
+
+ @Override
+ public String getValue(String propertyName) {
+ return CONFIG.get(propertyName);
+ }
+
+ @Override
+ public String getName() {
+ return TestLraCoordinator.ROUTING_NAME;
+ }
+}
diff --git a/microprofile/lra/testing/src/main/java/io/helidon/microprofile/testing/lra/package-info.java b/microprofile/lra/testing/src/main/java/io/helidon/microprofile/testing/lra/package-info.java
new file mode 100644
index 00000000000..a1737087e36
--- /dev/null
+++ b/microprofile/lra/testing/src/main/java/io/helidon/microprofile/testing/lra/package-info.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Test LRA coordinator.
+ * Allows simplified testing of LRA enabled JAX-RS resources.
+ *
+ * {@code
+ * @HelidonTest
+ * @AddBean(TestLraCoordinator.class)
+ * @Path("/test")
+ * public class LraTest {
+ *
+ * private final WebTarget target;
+ * private final Set completedLras;
+ * private final Set cancelledLras;
+ * private final TestLraCoordinator coordinator;
+ *
+ * @Inject
+ * public LraTest(WebTarget target,
+ * TestLraCoordinator coordinator) {
+ * this.target = target;
+ * this.coordinator = coordinator;
+ * this.completedLras = new CopyOnWriteArraySet<>();
+ * this.cancelledLras = new CopyOnWriteArraySet<>();
+ * }
+ *
+ * @PUT
+ * @Path("/withdraw")
+ * @LRA(LRA.Type.REQUIRES_NEW)
+ * public Response withdraw(@HeaderParam(LRA.LRA_HTTP_CONTEXT_HEADER) Optional lraId, String content) {
+ * ...
+ * return Response.ok().build();
+ * }
+ *
+ * @Complete
+ * public void complete(URI lraId) {
+ * completedLras.add(lraId.toString());
+ * }
+ *
+ * @Compensate
+ * public void rollback(URI lraId) {
+ * cancelledLras.add(lraId.toString());
+ * }
+ *
+ * @Test
+ * public void testLra() {
+ * try (Response res = target
+ * .path("/test/withdraw")
+ * .request()
+ * .put(Entity.entity("test", MediaType.TEXT_PLAIN_TYPE))) {
+ * assertThat(res.getStatus(), is(200));
+ * String lraId = res.getHeaderString(LRA.LRA_HTTP_CONTEXT_HEADER);
+ * Lra lra = coordinator.lra(lraId);
+ * assertThat(lra.status(), is(LRAStatus.Closed));
+ * assertThat(completedLras, contains(lraId));
+ * }
+ * }
+ * }
+ * }
+ */
+package io.helidon.microprofile.testing.lra;
diff --git a/microprofile/lra/testing/src/main/java/module-info.java b/microprofile/lra/testing/src/main/java/module-info.java
new file mode 100644
index 00000000000..d6c8c402868
--- /dev/null
+++ b/microprofile/lra/testing/src/main/java/module-info.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.eclipse.microprofile.config.spi.ConfigSource;
+
+/**
+ * Test LRA coordinator.
+ */
+module io.helidon.microprofile.testing.lra {
+
+ requires io.helidon.config.mp;
+ requires io.helidon.config.yaml.mp;
+ requires io.helidon.microprofile.cdi;
+ requires jakarta.inject;
+
+ requires transitive jakarta.cdi;
+ requires transitive jakarta.ws.rs;
+
+ requires static io.helidon.microprofile.server;
+ requires io.helidon.lra.coordinator;
+ requires io.helidon.microprofile.lra;
+
+ exports io.helidon.microprofile.testing.lra;
+
+ provides org.eclipse.microprofile.config.spi.ConfigSource
+ with io.helidon.microprofile.testing.lra.TestLraCoordinatorConfigSource;
+
+}
diff --git a/microprofile/lra/testing/src/test/java/io/helidon/microprofile/testing/lra/LraDisabledDiscoveryResourceTest.java b/microprofile/lra/testing/src/test/java/io/helidon/microprofile/testing/lra/LraDisabledDiscoveryResourceTest.java
new file mode 100644
index 00000000000..77607fc7005
--- /dev/null
+++ b/microprofile/lra/testing/src/test/java/io/helidon/microprofile/testing/lra/LraDisabledDiscoveryResourceTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.helidon.microprofile.testing.lra;
+
+import java.net.URI;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import io.helidon.lra.coordinator.Lra;
+import io.helidon.microprofile.config.ConfigCdiExtension;
+import io.helidon.microprofile.lra.LraCdiExtension;
+import io.helidon.microprofile.testing.junit5.AddBean;
+import io.helidon.microprofile.testing.junit5.AddExtension;
+import io.helidon.microprofile.testing.junit5.AddJaxRs;
+import io.helidon.microprofile.testing.junit5.DisableDiscovery;
+import io.helidon.microprofile.testing.junit5.HelidonTest;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.eclipse.microprofile.lra.annotation.Compensate;
+import org.eclipse.microprofile.lra.annotation.Complete;
+import org.eclipse.microprofile.lra.annotation.LRAStatus;
+import org.eclipse.microprofile.lra.annotation.ws.rs.LRA;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.is;
+
+@HelidonTest
+@DisableDiscovery
+@AddJaxRs
+@AddBean(TestLraCoordinator.class)
+@AddExtension(LraCdiExtension.class)
+@AddExtension(ConfigCdiExtension.class)
+@Path("/test/internal")
+public class LraDisabledDiscoveryResourceTest {
+
+ private final WebTarget target;
+ private final Set completedLras;
+ private final Set cancelledLras;
+ private final TestLraCoordinator coordinator;
+
+ @Inject
+ public LraDisabledDiscoveryResourceTest(WebTarget target,
+ TestLraCoordinator coordinator) {
+ this.target = target;
+ this.coordinator = coordinator;
+ this.completedLras = new CopyOnWriteArraySet<>();
+ this.cancelledLras = new CopyOnWriteArraySet<>();
+ }
+
+ @PUT
+ @Path("/withdraw")
+ @LRA(LRA.Type.REQUIRES_NEW)
+ public Response withdraw(@HeaderParam(LRA.LRA_HTTP_CONTEXT_HEADER) Optional lraId, String content) {
+ if ("BOOM".equals(content)) {
+ throw new IllegalArgumentException("BOOM");
+ }
+ return Response.ok().build();
+ }
+
+ @Complete
+ public void complete(URI lraId) {
+ completedLras.add(lraId.toString());
+ }
+
+ @Compensate
+ public void rollback(URI lraId) {
+ cancelledLras.add(lraId.toString());
+ }
+
+ @Test
+ public void testLraComplete() {
+ try (Response res = target
+ .path("/test/internal/withdraw")
+ .request()
+ .put(Entity.entity("test", MediaType.TEXT_PLAIN_TYPE))) {
+ assertThat(res.getStatus(), is(200));
+ String lraId = res.getHeaderString(LRA.LRA_HTTP_CONTEXT_HEADER);
+ Lra lra = coordinator.lra(lraId);
+ assertThat(lra.status(), is(LRAStatus.Closed));
+ assertThat(completedLras, contains(lraId));
+ }
+ }
+
+ @Test
+ public void testLraCompensate() {
+ try (Response res = target
+ .path("/test/internal/withdraw")
+ .request()
+ .put(Entity.entity("BOOM", MediaType.TEXT_PLAIN_TYPE))) {
+ assertThat(res.getStatus(), is(500));
+ String lraId = res.getHeaderString(LRA.LRA_HTTP_CONTEXT_HEADER);
+ Lra lra = coordinator.lra(lraId);
+ assertThat(lra.status(), is(LRAStatus.Cancelled));
+ assertThat(cancelledLras, contains(lraId));
+ }
+ }
+}
diff --git a/microprofile/lra/testing/src/test/java/io/helidon/microprofile/testing/lra/LraExternalResourceTest.java b/microprofile/lra/testing/src/test/java/io/helidon/microprofile/testing/lra/LraExternalResourceTest.java
new file mode 100644
index 00000000000..b2cf90842d6
--- /dev/null
+++ b/microprofile/lra/testing/src/test/java/io/helidon/microprofile/testing/lra/LraExternalResourceTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.helidon.microprofile.testing.lra;
+
+import io.helidon.lra.coordinator.Lra;
+import io.helidon.microprofile.testing.junit5.AddBean;
+import io.helidon.microprofile.testing.junit5.HelidonTest;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.eclipse.microprofile.lra.annotation.LRAStatus;
+import org.eclipse.microprofile.lra.annotation.ws.rs.LRA;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.is;
+
+@HelidonTest
+@AddBean(WithdrawTestResource.class)
+@AddBean(TestLraCoordinator.class)
+public class LraExternalResourceTest {
+
+ private final WithdrawTestResource withdrawTestResource;
+ private final TestLraCoordinator coordinator;
+ private final WebTarget target;
+
+ @Inject
+ public LraExternalResourceTest(WithdrawTestResource withdrawTestResource, TestLraCoordinator coordinator, WebTarget target) {
+ this.withdrawTestResource = withdrawTestResource;
+ this.coordinator = coordinator;
+ this.target = target;
+ }
+
+ @Test
+ public void testLraComplete() {
+ try (Response res = target
+ .path("/test/external/withdraw")
+ .request()
+ .put(Entity.entity("test", MediaType.TEXT_PLAIN_TYPE))) {
+ assertThat(res.getStatus(), is(200));
+ String lraId = res.getHeaderString(LRA.LRA_HTTP_CONTEXT_HEADER);
+ Lra lra = coordinator.lra(lraId);
+ assertThat(lra.status(), is(LRAStatus.Closed));
+ assertThat(withdrawTestResource.getCompletedLras(), contains(lraId));
+ }
+ }
+
+ @Test
+ public void testLraCompensate() {
+ try (Response res = target
+ .path("/test/external/withdraw")
+ .request()
+ .put(Entity.entity("BOOM", MediaType.TEXT_PLAIN_TYPE))) {
+ assertThat(res.getStatus(), is(500));
+ String lraId = res.getHeaderString(LRA.LRA_HTTP_CONTEXT_HEADER);
+ Lra lra = coordinator.lra(lraId);
+ assertThat(lra.status(), is(LRAStatus.Cancelled));
+ assertThat(withdrawTestResource.getCancelledLras(), contains(lraId));
+ }
+ }
+}
diff --git a/microprofile/lra/testing/src/test/java/io/helidon/microprofile/testing/lra/LraMultiPortTest.java b/microprofile/lra/testing/src/test/java/io/helidon/microprofile/testing/lra/LraMultiPortTest.java
new file mode 100644
index 00000000000..a0487365e1a
--- /dev/null
+++ b/microprofile/lra/testing/src/test/java/io/helidon/microprofile/testing/lra/LraMultiPortTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.helidon.microprofile.testing.lra;
+
+import java.net.URI;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import io.helidon.lra.coordinator.Lra;
+import io.helidon.microprofile.server.RoutingName;
+import io.helidon.microprofile.server.RoutingPath;
+import io.helidon.microprofile.testing.junit5.AddBean;
+import io.helidon.microprofile.testing.junit5.AddConfig;
+import io.helidon.microprofile.testing.junit5.HelidonTest;
+import io.helidon.microprofile.testing.junit5.Socket;
+import io.helidon.webserver.http.HttpService;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.inject.Produces;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.eclipse.microprofile.lra.annotation.Compensate;
+import org.eclipse.microprofile.lra.annotation.Complete;
+import org.eclipse.microprofile.lra.annotation.LRAStatus;
+import org.eclipse.microprofile.lra.annotation.ws.rs.LRA;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.is;
+
+@HelidonTest
+@AddConfig(key = "server.sockets.0.name", value = "test-route")
+@AddConfig(key = "server.sockets.0.port", value = "0")
+@AddConfig(key = "server.sockets.0.bind-address", value = "localhost")
+@AddBean(TestLraCoordinator.class)
+@Path("/test/multi-port")
+public class LraMultiPortTest {
+
+ private final WebTarget target;
+ private final WebTarget otherTarget;
+ private final Set completedLras;
+ private final Set cancelledLras;
+ private final TestLraCoordinator coordinator;
+
+ @Inject
+ public LraMultiPortTest(WebTarget target,
+ TestLraCoordinator coordinator,
+ @Socket("test-route") WebTarget otherTarget) {
+ this.target = target;
+ this.coordinator = coordinator;
+ this.otherTarget = otherTarget;
+ this.completedLras = new CopyOnWriteArraySet<>();
+ this.cancelledLras = new CopyOnWriteArraySet<>();
+ }
+
+ @Produces
+ @ApplicationScoped
+ @RoutingName("test-route")
+ @RoutingPath("/test/route")
+ public HttpService anotherRoute() {
+ return r -> r.any((req, res) -> res.send("Hello from test route!"));
+ }
+
+ @PUT
+ @Path("/outer")
+ @LRA(LRA.Type.REQUIRES_NEW)
+ public Response withdraw(@HeaderParam(LRA.LRA_HTTP_CONTEXT_HEADER) Optional lraId, String content) {
+ try (Response res = target.path("/test/multi-port/inner")
+ .request()
+ .put(Entity.entity(content, MediaType.TEXT_PLAIN_TYPE))) {
+ assertThat(res.getStatus(), is(Response.Status.OK.getStatusCode()));
+ }
+ return Response.ok().build();
+ }
+
+ @PUT
+ @Path("/inner")
+ @LRA(LRA.Type.REQUIRED)
+ public Response deposit(@HeaderParam(LRA.LRA_HTTP_CONTEXT_HEADER) Optional lraId, String content) {
+ if ("BOOM".equals(content)) {
+ throw new IllegalArgumentException("BOOM");
+ }
+ return Response.ok().build();
+ }
+
+ @Complete
+ public void complete(URI lraId) {
+ completedLras.add(lraId.toString());
+ }
+
+ @Compensate
+ public void rollback(URI lraId) {
+ cancelledLras.add(lraId.toString());
+ }
+
+ @Test
+ public void testLra() {
+ try (Response res = target
+ .path("/test/multi-port/outer")
+ .request()
+ .put(Entity.entity("test", MediaType.TEXT_PLAIN_TYPE))) {
+ assertThat(res.getStatus(), is(200));
+ String lraId = res.getHeaderString(LRA.LRA_HTTP_CONTEXT_HEADER);
+ Lra lra = coordinator.lra(lraId);
+ assertThat(lra.status(), is(LRAStatus.Closed));
+ assertThat(completedLras, contains(lraId));
+ }
+ }
+
+ @Test
+ public void testCompensatedLra() {
+ try (Response res = target
+ .path("/test/multi-port/outer")
+ .request()
+ .put(Entity.entity("BOOM", MediaType.TEXT_PLAIN_TYPE))) {
+ assertThat(res.getStatus(), is(500));
+ String lraId = res.getHeaderString(LRA.LRA_HTTP_CONTEXT_HEADER);
+ Lra lra = coordinator.lra(lraId);
+ assertThat(lra.status(), is(LRAStatus.Cancelled));
+ assertThat(cancelledLras, contains(lraId));
+ }
+ }
+
+ @Test
+ public void testOtherRoute() {
+ try (Response res = otherTarget
+ .path("/test/route")
+ .request()
+ .get()) {
+ assertThat(res.getStatus(), is(200));
+ assertThat(res.readEntity(String.class), is("Hello from test route!"));
+ }
+ }
+
+}
diff --git a/microprofile/lra/testing/src/test/java/io/helidon/microprofile/testing/lra/NonLraResourceTest.java b/microprofile/lra/testing/src/test/java/io/helidon/microprofile/testing/lra/NonLraResourceTest.java
new file mode 100644
index 00000000000..774541b117c
--- /dev/null
+++ b/microprofile/lra/testing/src/test/java/io/helidon/microprofile/testing/lra/NonLraResourceTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.helidon.microprofile.testing.lra;
+
+import io.helidon.microprofile.testing.junit5.HelidonTest;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Response;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+@HelidonTest
+@Path("/test/non-lra")
+public class NonLraResourceTest {
+
+ private final WebTarget target;
+
+ @Inject
+ public NonLraResourceTest(WebTarget target) {
+ this.target = target;
+ }
+
+ @GET
+ @Path("/say-hi")
+ public String sayHi() {
+ return "Hi!";
+ }
+
+ @Test
+ public void testNonLraResource() {
+ try (Response res = target
+ .path("/test/non-lra/say-hi")
+ .request()
+ .get()) {
+ assertThat(res.getStatus(), is(200));
+ assertThat(res.readEntity(String.class), is("Hi!"));
+ }
+ }
+}
diff --git a/microprofile/lra/testing/src/test/java/io/helidon/microprofile/testing/lra/WithdrawTestResource.java b/microprofile/lra/testing/src/test/java/io/helidon/microprofile/testing/lra/WithdrawTestResource.java
new file mode 100644
index 00000000000..9487bc54b50
--- /dev/null
+++ b/microprofile/lra/testing/src/test/java/io/helidon/microprofile/testing/lra/WithdrawTestResource.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.helidon.microprofile.testing.lra;
+
+import java.net.URI;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Response;
+import org.eclipse.microprofile.lra.annotation.Compensate;
+import org.eclipse.microprofile.lra.annotation.Complete;
+import org.eclipse.microprofile.lra.annotation.ws.rs.LRA;
+
+@ApplicationScoped
+@Path("/test/external")
+public class WithdrawTestResource {
+
+ private final Set completedLras;
+ private final Set cancelledLras;
+
+ public WithdrawTestResource() {
+ this.completedLras = new CopyOnWriteArraySet<>();
+ this.cancelledLras = new CopyOnWriteArraySet<>();
+ }
+
+ @PUT
+ @Path("/withdraw")
+ @LRA(LRA.Type.REQUIRES_NEW)
+ public Response withdraw(@HeaderParam(LRA.LRA_HTTP_CONTEXT_HEADER) Optional lraId, String content) {
+ if ("BOOM".equals(content)) {
+ throw new IllegalArgumentException("BOOM");
+ }
+ return Response.ok().build();
+ }
+
+ @Complete
+ public void complete(URI lraId) {
+ completedLras.add(lraId.toString());
+ }
+
+ @Compensate
+ public void rollback(URI lraId) {
+ cancelledLras.add(lraId.toString());
+ }
+
+ Set getCompletedLras() {
+ return completedLras;
+ }
+
+ Set getCancelledLras() {
+ return cancelledLras;
+ }
+}
diff --git a/microprofile/lra/testing/src/test/resources/logging-test.properties b/microprofile/lra/testing/src/test/resources/logging-test.properties
new file mode 100644
index 00000000000..a61f39ea0cb
--- /dev/null
+++ b/microprofile/lra/testing/src/test/resources/logging-test.properties
@@ -0,0 +1,25 @@
+#
+# Copyright (c) 2024 Oracle and/or its affiliates.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+handlers=io.helidon.logging.jul.HelidonConsoleHandler
+
+# HelidonConsoleHandler uses a SimpleFormatter subclass that replaces "!thread!" with the current thread
+java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n
+
+# Global logging level. Can be overridden by specific loggers
+.level=WARNING
+
+io.helidon.level=INFO