diff --git a/spec/src/main/asciidoc/optional-container-integration.asciidoc b/spec/src/main/asciidoc/optional-container-integration.asciidoc deleted file mode 100644 index a44196df..00000000 --- a/spec/src/main/asciidoc/optional-container-integration.asciidoc +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) 2020 Contributors to the Eclipse Foundation -// -// See the NOTICE file(s) distributed with this work for additional -// information regarding copyright ownership. -// -// 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. -// Contributors: -// Ladislav Thon - -[[optional-container-integration]] - -== Recommendations for Optional Container Integration - -This section describes the expected behaviors when the implementation runs in a Jakarta EE container. - -=== `@Asynchronous` - -Threads that are servicing `@Asynchronous` invocations should, for the duration of the invocation, have the correct security context and naming context associated. diff --git a/spec/src/main/asciidoc/optional-integrations.asciidoc b/spec/src/main/asciidoc/optional-integrations.asciidoc new file mode 100644 index 00000000..f40bd340 --- /dev/null +++ b/spec/src/main/asciidoc/optional-integrations.asciidoc @@ -0,0 +1,57 @@ +// +// Copyright (c) 2020 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// 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. +// Contributors: +// Ladislav Thon + +[[optional-integrations]] + +== Recommendations for Optional Integrations + +=== Jakarta EE + +This section describes the expected behaviors when the implementation runs in a Jakarta EE container. + +==== `@Asynchronous` + +Threads that are servicing `@Asynchronous` invocations should, for the duration of the invocation, have the correct security context and naming context associated. + +=== MicroProfile Context Propagation + +This section describes the expected behaviors when the implementation runs in an environment that provides implementation of MicroProfile Context Propagation. +These behaviors are currently optional because the MicroProfile Context Propagation specification is not part of the MicroProfile Platform. + +==== `@Asynchronous` + +Implementations should use MicroProfile Context Propagation to propagate contexts to threads that are servicing `@Asynchronous` invocations. +Deciding which contexts are propagated and which are cleared is left to the MicroProfile Context Propagation implementation. + +[NOTE] +==== +As of version 1.0.2, MicroProfile Context Propagation doesn't define which contexts are propagated and which are cleared by default, this is left to implementations. + +However, there are configuration properties that you can use to override the default setting. +==== + +If the environment that provides MicroProfile Context Propagation is itself a Jakarta EE container, the _Jakarta EE_ section above doesn't apply and context propagation is left entirely to MicroProfile Context Propagation. + +[NOTE] +==== +The _Asynchronous Usage_ chapter specifies that "context for `RequestScoped` must be active during the asynchronous method invocation". +When MicroProfile Context Propagation is used, this still applies. +The difference is that the request context will be not only active, but also propagated. +==== diff --git a/tck/pom.xml b/tck/pom.xml index 681416b9..2bc74197 100644 --- a/tck/pom.xml +++ b/tck/pom.xml @@ -32,6 +32,7 @@ 1.1.14.Final ^_?[a-z][a-zA-Z0-9_]*$ 1.3 + 1.0.2 @@ -75,6 +76,13 @@ provided + + org.eclipse.microprofile.context-propagation + microprofile-context-propagation-api + ${microprofile-context-propagation-api.version} + provided + + org.apache.geronimo.specs diff --git a/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/ContextPropagationTest.java b/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/ContextPropagationTest.java new file mode 100644 index 00000000..eae08679 --- /dev/null +++ b/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/ContextPropagationTest.java @@ -0,0 +1,114 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * 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 org.eclipse.microprofile.fault.tolerance.tck.context.propagation; + +import org.eclipse.microprofile.context.spi.ThreadContextProvider; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.testng.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.testng.SkipException; +import org.testng.annotations.Test; + +import javax.inject.Inject; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import static org.eclipse.microprofile.fault.tolerance.tck.asynchronous.CompletableFutureHelper.toCompletableFuture; +import static org.testng.Assert.assertEquals; + +public class ContextPropagationTest extends Arquillian { + // configure identical defaults for both ManagedExecutor and ThreadContext, because implementations + // are free to use any of them to implement context propagation + private static final String CONTEXT_PROPAGATION_CONFIG = "" + + "mp.context.ManagedExecutor.propagated=CDI,MyContext1\n" + + "mp.context.ManagedExecutor.cleared=MyContext2\n" + + "mp.context.ThreadContext.propagated=CDI,MyContext1\n" + + "mp.context.ThreadContext.cleared=MyContext2\n"; + + @Deployment + public static WebArchive deploy() { + JavaArchive jar = ShrinkWrap.create(JavaArchive.class, "ftContextPropagation.jar") + .addClasses(MyAppScopedBean.class, MyReqScopedBean.class) + .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); + + + if (contextPropagationPresent()) { + // if this was always added, deployment would fail at runtime + // when MP Context Propagation classes are not present + + jar.addClasses(MyContext1.class, MyContext1Provider.class, MyContext2.class, MyContext2Provider.class) + .addAsServiceProvider(ThreadContextProvider.class, MyContext1Provider.class, MyContext2Provider.class) + .addAsManifestResource(new StringAsset(CONTEXT_PROPAGATION_CONFIG), "microprofile-config.properties"); + + } + + return ShrinkWrap.create(WebArchive.class, "ftContextPropagation.war") + .addAsLibrary(jar); + } + + @Inject + private MyAppScopedBean appScopedBean; + + @Inject + private MyReqScopedBean reqScopedBean; + + @Test + public void contextPropagation() throws InterruptedException, ExecutionException, TimeoutException { + assumeContextPropagationPresence(); + + MyContext1.set("foo"); + MyContext2.set("bar"); + reqScopedBean.set("quux"); + + assertEquals(MyContext1.get(), "foo"); + assertEquals(MyContext2.get(), "bar"); + assertEquals(reqScopedBean.get(), "quux"); + + // in the @Asynchronous method, CDI should be propagated, MyContext1 should be propagated, + // and MyContext2 should be cleared + String value = toCompletableFuture(appScopedBean.get()).get(1, TimeUnit.MINUTES); + assertEquals(value, "foo|[[NONE]]|quux"); + + assertEquals(MyContext1.get(), "foo"); + assertEquals(MyContext2.get(), "bar"); + assertEquals(reqScopedBean.get(), "quux"); + } + + private static void assumeContextPropagationPresence() { + if (!contextPropagationPresent()) { + throw new SkipException("Context Propagation not present, ignoring test"); + } + } + + private static boolean contextPropagationPresent() { + try { + Class.forName("org.eclipse.microprofile.context.ThreadContext"); + return true; + } + catch (ClassNotFoundException e) { + return false; + } + } +} diff --git a/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyAppScopedBean.java b/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyAppScopedBean.java new file mode 100644 index 00000000..cfa227a7 --- /dev/null +++ b/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyAppScopedBean.java @@ -0,0 +1,39 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * 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 org.eclipse.microprofile.fault.tolerance.tck.context.propagation; + +import org.eclipse.microprofile.faulttolerance.Asynchronous; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import java.util.concurrent.CompletionStage; + +import static java.util.concurrent.CompletableFuture.completedFuture; + +@ApplicationScoped +public class MyAppScopedBean { + @Inject + private MyReqScopedBean reqScopedBean; + + @Asynchronous + public CompletionStage get() { + return completedFuture(MyContext1.get() + "|" + MyContext2.get() + "|" + reqScopedBean.get()); + } +} diff --git a/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyContext1.java b/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyContext1.java new file mode 100644 index 00000000..ecbd9aab --- /dev/null +++ b/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyContext1.java @@ -0,0 +1,38 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * 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 org.eclipse.microprofile.fault.tolerance.tck.context.propagation; + +public class MyContext1 { + private static final ThreadLocal CONTEXTUAL_VALUE = ThreadLocal.withInitial(() -> "<>"); + + private MyContext1() {} // avoid instantiation + + public static String get() { + return CONTEXTUAL_VALUE.get(); + } + + public static void set(String value) { + CONTEXTUAL_VALUE.set(value); + } + + public static void remove() { + CONTEXTUAL_VALUE.remove(); + } +} diff --git a/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyContext1Provider.java b/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyContext1Provider.java new file mode 100644 index 00000000..c7d0d475 --- /dev/null +++ b/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyContext1Provider.java @@ -0,0 +1,55 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * 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 org.eclipse.microprofile.fault.tolerance.tck.context.propagation; + +import org.eclipse.microprofile.context.spi.ThreadContextProvider; +import org.eclipse.microprofile.context.spi.ThreadContextSnapshot; + +import java.util.Map; + +public class MyContext1Provider implements ThreadContextProvider { + @Override + public ThreadContextSnapshot currentContext(Map props) { + String captured = MyContext1.get(); + return () -> { + String movedOut = MyContext1.get(); + MyContext1.set(captured); + return () -> { + MyContext1.set(movedOut); + }; + }; + } + + @Override + public ThreadContextSnapshot clearedContext(Map props) { + return () -> { + String movedOut = MyContext1.get(); + MyContext1.remove(); + return () -> { + MyContext1.set(movedOut); + }; + }; + } + + @Override + public String getThreadContextType() { + return MyContext1.class.getSimpleName(); + } +} diff --git a/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyContext2.java b/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyContext2.java new file mode 100644 index 00000000..b7505480 --- /dev/null +++ b/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyContext2.java @@ -0,0 +1,38 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * 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 org.eclipse.microprofile.fault.tolerance.tck.context.propagation; + +public class MyContext2 { + private static final ThreadLocal CONTEXTUAL_VALUE = ThreadLocal.withInitial(() -> "[[NONE]]"); + + private MyContext2() {} // avoid instantiation + + public static String get() { + return CONTEXTUAL_VALUE.get(); + } + + public static void set(String value) { + CONTEXTUAL_VALUE.set(value); + } + + public static void remove() { + CONTEXTUAL_VALUE.remove(); + } +} diff --git a/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyContext2Provider.java b/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyContext2Provider.java new file mode 100644 index 00000000..464d67f3 --- /dev/null +++ b/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyContext2Provider.java @@ -0,0 +1,55 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * 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 org.eclipse.microprofile.fault.tolerance.tck.context.propagation; + +import org.eclipse.microprofile.context.spi.ThreadContextProvider; +import org.eclipse.microprofile.context.spi.ThreadContextSnapshot; + +import java.util.Map; + +public class MyContext2Provider implements ThreadContextProvider { + @Override + public ThreadContextSnapshot currentContext(Map props) { + String captured = MyContext2.get(); + return () -> { + String movedOut = MyContext2.get(); + MyContext2.set(captured); + return () -> { + MyContext2.set(movedOut); + }; + }; + } + + @Override + public ThreadContextSnapshot clearedContext(Map props) { + return () -> { + String movedOut = MyContext2.get(); + MyContext2.remove(); + return () -> { + MyContext2.set(movedOut); + }; + }; + } + + @Override + public String getThreadContextType() { + return MyContext2.class.getSimpleName(); + } +} diff --git a/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyReqScopedBean.java b/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyReqScopedBean.java new file mode 100644 index 00000000..302cc139 --- /dev/null +++ b/tck/src/main/java/org/eclipse/microprofile/fault/tolerance/tck/context/propagation/MyReqScopedBean.java @@ -0,0 +1,39 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * 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 org.eclipse.microprofile.fault.tolerance.tck.context.propagation; + +import javax.enterprise.context.RequestScoped; + +@RequestScoped +public class MyReqScopedBean { + private String value; + + public String get() { + return value; + } + + public void set(String value) { + this.value = value; + } + + public void remove() { + this.value = null; + } +}