From 88b4977783afbae8a0cbad20dddf15df46d7cfd3 Mon Sep 17 00:00:00 2001 From: Romain Grecourt Date: Tue, 4 Feb 2025 15:23:13 -0800 Subject: [PATCH] Use actions/cache v4.2.0 (#9729) * Use actions/cache v4.2.0 * Fix TestSpanListenersWithInjection to register listener on CDI container startup. - Move io.helidon.common.Functions.UncheckedException to io.helidon.common.UncheckedException - Fix InvocationTargetException handling for the instrumented invocations --- .github/actions/common/action.yml | 8 ++--- .../java/io/helidon/common/Functions.java | 17 ---------- .../io/helidon/common/UncheckedException.java | 31 +++++++++++++++++++ .../TestSpanListenersWithInjection.java | 28 ++++++++--------- .../microprofile/testing/Instrumented.java | 12 ++++++- .../testing/ReflectionHelper.java | 12 +++---- .../testing/testng/HelidonTestNgListener.java | 10 +++--- 7 files changed, 69 insertions(+), 49 deletions(-) create mode 100644 common/common/src/main/java/io/helidon/common/UncheckedException.java diff --git a/.github/actions/common/action.yml b/.github/actions/common/action.yml index 950858271d7..e2c60b01f21 100644 --- a/.github/actions/common/action.yml +++ b/.github/actions/common/action.yml @@ -84,7 +84,7 @@ runs: java-version: ${{ env.JAVA_VERSION }} - name: Cache local Maven repository (read-write) if: ${{ inputs.maven-cache == 'read-write' }} - uses: actions/cache@v4.0.2 + uses: actions/cache@v4.2.0 with: # See https://github.com/actions/toolkit/issues/713 # Include must not match top level directories @@ -98,7 +98,7 @@ runs: local-maven- - name: Cache local Maven repository (read-only) if: ${{ inputs.maven-cache == 'read-only' }} - uses: actions/cache/restore@v4.0.2 + uses: actions/cache/restore@v4.2.0 with: path: | .m2/repository/**/*.* @@ -109,7 +109,7 @@ runs: local-maven- - name: Build cache (read-write) if: ${{ inputs.build-cache == 'read-write' }} - uses: actions/cache@v4.0.2 + uses: actions/cache@v4.2.0 with: path: | ./**/target/** @@ -121,7 +121,7 @@ runs: build-cache-${{ github.run_id }}- - name: Build cache (read-only) if: ${{ inputs.build-cache == 'read-only' }} - uses: actions/cache/restore@v4.0.2 + uses: actions/cache/restore@v4.2.0 with: path: | ./**/target/** diff --git a/common/common/src/main/java/io/helidon/common/Functions.java b/common/common/src/main/java/io/helidon/common/Functions.java index f87bcae9f84..f5a384c2c8a 100644 --- a/common/common/src/main/java/io/helidon/common/Functions.java +++ b/common/common/src/main/java/io/helidon/common/Functions.java @@ -246,21 +246,4 @@ public interface CheckedSupplier { */ T get() throws E; } - - /** - * Unchecked exception. - * - * @see #unwrap(Throwable) - */ - public static class UncheckedException extends RuntimeException { - - /** - * Create a new unchecked exception. - * - * @param cause cause - */ - public UncheckedException(Throwable cause) { - super(cause); - } - } } diff --git a/common/common/src/main/java/io/helidon/common/UncheckedException.java b/common/common/src/main/java/io/helidon/common/UncheckedException.java new file mode 100644 index 00000000000..f8bad45b079 --- /dev/null +++ b/common/common/src/main/java/io/helidon/common/UncheckedException.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 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.common; + +/** + * Unchecked exception. + */ +public class UncheckedException extends RuntimeException { + + /** + * Create a new unchecked exception. + * + * @param cause cause + */ + public UncheckedException(Throwable cause) { + super(cause); + } +} diff --git a/microprofile/telemetry/src/test/java/io/helidon/microprofile/telemetry/TestSpanListenersWithInjection.java b/microprofile/telemetry/src/test/java/io/helidon/microprofile/telemetry/TestSpanListenersWithInjection.java index 8844e3657c6..f15ea51943c 100644 --- a/microprofile/telemetry/src/test/java/io/helidon/microprofile/telemetry/TestSpanListenersWithInjection.java +++ b/microprofile/telemetry/src/test/java/io/helidon/microprofile/telemetry/TestSpanListenersWithInjection.java @@ -28,8 +28,10 @@ import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.context.Scope; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Initialized; +import jakarta.enterprise.event.Observes; import jakarta.inject.Inject; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -41,21 +43,18 @@ @AddBean(TestSpanListenersWithInjection.MyBean.class) class TestSpanListenersWithInjection { - private static MyListener listener; + private static final MyListener LISTENER = new MyListener(); @Inject private MyBean myBean; - @BeforeAll - static void setup() { - listener = new MyListener(); - io.helidon.tracing.Tracer.global().register(listener); - } - @BeforeEach void clearListener() { - listener.clear(); + LISTENER.clear(); + } + void onStartup(@Observes @Initialized(ApplicationScoped.class) Object event) { + io.helidon.tracing.Tracer.global().register(LISTENER); } @Test @@ -108,13 +107,14 @@ private void checkListenerCounts(String message, int expectedEnded, int expectedActivated, int expectedClosed) { - assertThat(message + ": Starting spans", listener.starting(), hasSize(expectedStarting)); - assertThat(message + ": Started spans", listener.started(), hasSize(expectedStarted)); - assertThat(message + ": Ended spans", listener.ended(), hasSize(expectedEnded)); - assertThat(message + ": Activated scopes", listener.activated().keySet(), hasSize(expectedActivated)); - assertThat(message + ": Closed scopes", listener.closed().keySet(), hasSize(expectedClosed)); + assertThat(message + ": Starting spans", LISTENER.starting(), hasSize(expectedStarting)); + assertThat(message + ": Started spans", LISTENER.started(), hasSize(expectedStarted)); + assertThat(message + ": Ended spans", LISTENER.ended(), hasSize(expectedEnded)); + assertThat(message + ": Activated scopes", LISTENER.activated().keySet(), hasSize(expectedActivated)); + assertThat(message + ": Closed scopes", LISTENER.closed().keySet(), hasSize(expectedClosed)); } + @ApplicationScoped static class MyBean { @Inject diff --git a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/Instrumented.java b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/Instrumented.java index e83c8c19d3f..aa0f0f2152d 100644 --- a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/Instrumented.java +++ b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/Instrumented.java @@ -19,12 +19,15 @@ import java.lang.invoke.MethodHandles; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import java.util.function.BiFunction; import java.util.stream.Stream; +import io.helidon.common.UncheckedException; + import net.bytebuddy.ByteBuddy; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.dynamic.DynamicType; @@ -100,7 +103,14 @@ static Class instrument(Class type, return instrument(type, annotations, methodExcludes, (proxy, method, args) -> { T instance = resolver.apply(type, method); if (instance != null) { - return invoke(Object.class, method, instance, args); + try { + return invoke(Object.class, method, instance, args); + } catch (UncheckedException e) { + if (e.getCause() instanceof InvocationTargetException te) { + throw te; + } + throw e; + } } return null; }); diff --git a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/ReflectionHelper.java b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/ReflectionHelper.java index e9c1aed8492..79c732e7862 100644 --- a/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/ReflectionHelper.java +++ b/microprofile/testing/testing/src/main/java/io/helidon/microprofile/testing/ReflectionHelper.java @@ -30,6 +30,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import io.helidon.common.UncheckedException; + /** * Reflection helper. */ @@ -285,14 +287,8 @@ static T invoke(Class type, Method method, Object instance, Object... arg method.setAccessible(true); Object value = method.invoke(instance, args); return type.cast(value); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } catch (InvocationTargetException e) { - Throwable target = e.getTargetException(); - if (e.getTargetException() instanceof RuntimeException re) { - throw re; - } - throw new RuntimeException(target); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new UncheckedException(e); } } } diff --git a/microprofile/testing/testng/src/main/java/io/helidon/microprofile/testing/testng/HelidonTestNgListener.java b/microprofile/testing/testng/src/main/java/io/helidon/microprofile/testing/testng/HelidonTestNgListener.java index da9bf75bb79..737101d2605 100644 --- a/microprofile/testing/testng/src/main/java/io/helidon/microprofile/testing/testng/HelidonTestNgListener.java +++ b/microprofile/testing/testng/src/main/java/io/helidon/microprofile/testing/testng/HelidonTestNgListener.java @@ -31,7 +31,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Semaphore; -import io.helidon.common.Functions.UncheckedException; +import io.helidon.common.UncheckedException; import io.helidon.common.context.Context; import io.helidon.common.context.Contexts; import io.helidon.microprofile.testing.HelidonTestContainer; @@ -268,13 +268,13 @@ private Object invoke(Object proxy, Method method, Object[] args) throws Throwab method.setAccessible(true); return method.invoke(instance, args); } catch (InvocationTargetException e) { - if (e.getTargetException() instanceof RuntimeException) { - throw (RuntimeException) e.getTargetException(); - } - throw new UncheckedException(e.getTargetException()); + throw new UncheckedException(e); } }); } catch (UncheckedException e) { + if (e.getCause() instanceof InvocationTargetException te) { + throw te.getCause(); + } throw e.getCause(); } }