From 38185b687a50035053d5cb85a30e138a39c34a97 Mon Sep 17 00:00:00 2001 From: Matej Novotny Date: Wed, 21 Jun 2023 11:15:08 +0200 Subject: [PATCH 1/2] Upgrade Weld to 5.1.1.Final --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b6ad9eb3..3cc49d38 100644 --- a/pom.xml +++ b/pom.xml @@ -70,7 +70,7 @@ 3.1.6 6.14.3 5.0.SP3 - 5.1.0.Final + 5.1.1.Final 4.0.0.Final 0.8.10 From 57af00ec308bc99680d75190ace5bd9fb6667312 Mon Sep 17 00:00:00 2001 From: Matej Novotny Date: Wed, 21 Jun 2023 11:13:16 +0200 Subject: [PATCH 2/2] Rework DefaultMethodTest to use InterceptionFactory --- .../InterceptingInvocationHandler.java | 204 ------------------ .../InterfaceBasedExtension.java | 9 +- 2 files changed, 5 insertions(+), 208 deletions(-) delete mode 100644 testsuite/basic/src/test/java/io/smallrye/faulttolerance/defaultmethod/InterceptingInvocationHandler.java diff --git a/testsuite/basic/src/test/java/io/smallrye/faulttolerance/defaultmethod/InterceptingInvocationHandler.java b/testsuite/basic/src/test/java/io/smallrye/faulttolerance/defaultmethod/InterceptingInvocationHandler.java deleted file mode 100644 index 9ebca670..00000000 --- a/testsuite/basic/src/test/java/io/smallrye/faulttolerance/defaultmethod/InterceptingInvocationHandler.java +++ /dev/null @@ -1,204 +0,0 @@ -package io.smallrye.faulttolerance.defaultmethod; - -import static io.smallrye.faulttolerance.core.util.SneakyThrow.sneakyThrow; - -import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import jakarta.enterprise.context.spi.CreationalContext; -import jakarta.enterprise.inject.spi.BeanManager; -import jakarta.enterprise.inject.spi.InterceptionType; -import jakarta.enterprise.inject.spi.Interceptor; -import jakarta.interceptor.InvocationContext; - -// adapted from https://github.com/resteasy/resteasy-microprofile/tree/main/rest-client-base/src/main/java/org/jboss/resteasy/microprofile/client -// which is Apache 2.0 licensed -public class InterceptingInvocationHandler implements InvocationHandler { - private final Object target; - - private final Map> interceptorChains; - - public InterceptingInvocationHandler(Class iface, Object target, BeanManager beanManager) { - this.target = target; - - // this CreationalContext is never released, but that's ok _in a test_ - CreationalContext creationalContext = beanManager.createCreationalContext(null); - this.interceptorChains = initInterceptorChains(beanManager, creationalContext, iface); - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - List chain = interceptorChains.get(method); - if (chain != null) { - return new InvocationContextImpl(target, method, args, chain).proceed(); - } else { - try { - return method.invoke(target, args); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - } - } - - private static Map> initInterceptorChains(BeanManager beanManager, - CreationalContext creationalContext, Class iface) { - - Map> chains = new HashMap<>(); - Map, Object> interceptorInstances = new HashMap<>(); - - List classLevelBindings = getBindings(iface, beanManager); - - for (Method method : iface.getMethods()) { - if (method.isDefault() || Modifier.isStatic(method.getModifiers())) { - continue; - } - - List methodLevelBindings = getBindings(method, beanManager); - if (!classLevelBindings.isEmpty() || !methodLevelBindings.isEmpty()) { - Annotation[] interceptorBindings = mergeBindings(methodLevelBindings, classLevelBindings); - - List> interceptors = beanManager.resolveInterceptors(InterceptionType.AROUND_INVOKE, - interceptorBindings); - if (!interceptors.isEmpty()) { - List chain = new ArrayList<>(); - for (Interceptor interceptor : interceptors) { - chain.add(new InterceptorInvocation((Interceptor) interceptor, - interceptorInstances.computeIfAbsent(interceptor, - i -> beanManager.getReference(i, i.getBeanClass(), creationalContext)))); - } - chains.put(method, chain); - } - } - } - - return chains; - } - - private static List getBindings(AnnotatedElement annotated, BeanManager beanManager) { - Annotation[] annotations = annotated.getAnnotations(); - if (annotations.length == 0) { - return Collections.emptyList(); - } - List bindings = new ArrayList<>(); - for (Annotation annotation : annotations) { - if (beanManager.isInterceptorBinding(annotation.annotationType())) { - bindings.add(annotation); - } - } - return bindings; - } - - private static Annotation[] mergeBindings(List methodLevel, List classLevel) { - Set> methodLevelTypes = methodLevel.stream() - .map(Annotation::annotationType) - .collect(Collectors.toSet()); - - List result = new ArrayList<>(methodLevel); - for (Annotation classLevelBinding : classLevel) { - if (!methodLevelTypes.contains(classLevelBinding.annotationType())) { - result.add(classLevelBinding); - } - } - return result.toArray(new Annotation[0]); - } - - private static class InvocationContextImpl implements InvocationContext { - private final Object target; - private final Method method; - private Object[] arguments; - private final Map contextData; - - private final List chain; - private final int position; - - public InvocationContextImpl(Object target, Method method, Object[] arguments, - List chain) { - this(target, method, arguments, chain, 0); - } - - private InvocationContextImpl(Object target, Method method, Object[] arguments, - List chain, int position) { - this.target = target; - this.method = method; - this.arguments = arguments; - this.contextData = new HashMap<>(); - this.chain = chain; - this.position = position; - } - - @Override - public Object proceed() throws Exception { - try { - if (position < chain.size()) { - InvocationContextImpl ctx = new InvocationContextImpl(target, method, arguments, chain, position + 1); - return chain.get(position).invoke(ctx); - } else { - return method.invoke(target, arguments); - } - } catch (InvocationTargetException e) { - throw sneakyThrow(e.getCause()); - } - } - - @Override - public Object getTarget() { - return target; - } - - @Override - public Method getMethod() { - return method; - } - - @Override - public Constructor getConstructor() { - return null; - } - - @Override - public Object[] getParameters() throws IllegalStateException { - return arguments; - } - - @Override - public void setParameters(Object[] args) throws IllegalStateException, IllegalArgumentException { - this.arguments = args; - } - - @Override - public Map getContextData() { - return contextData; - } - - @Override - public Object getTimer() { - return null; - } - } - - private static class InterceptorInvocation { - private final Interceptor interceptorBean; - private final Object interceptorInstance; - - public InterceptorInvocation(Interceptor interceptorBean, Object interceptorInstance) { - this.interceptorBean = interceptorBean; - this.interceptorInstance = interceptorInstance; - } - - public Object invoke(InvocationContext ctx) throws Exception { - return interceptorBean.intercept(InterceptionType.AROUND_INVOKE, interceptorInstance, ctx); - } - } -} diff --git a/testsuite/basic/src/test/java/io/smallrye/faulttolerance/defaultmethod/InterfaceBasedExtension.java b/testsuite/basic/src/test/java/io/smallrye/faulttolerance/defaultmethod/InterfaceBasedExtension.java index 5b11f924..f56ff958 100644 --- a/testsuite/basic/src/test/java/io/smallrye/faulttolerance/defaultmethod/InterfaceBasedExtension.java +++ b/testsuite/basic/src/test/java/io/smallrye/faulttolerance/defaultmethod/InterfaceBasedExtension.java @@ -37,18 +37,19 @@ public void rememberInterfaces(@Observes @WithAnnotations(RegisterInterfaceBased } } + @SuppressWarnings({ "rawtypes", "unchecked" }) public void registerBeans(@Observes AfterBeanDiscovery abd, BeanManager beanManager) { - for (Class iface : interfaces) { + for (Class iface : interfaces) { abd.addBean() .beanClass(iface) .types(iface) .scope(Dependent.class) .qualifiers(Default.Literal.INSTANCE, Any.Literal.INSTANCE, InterfaceBased.Literal.INSTANCE) .createWith(ctx -> { - Object target = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), + Object instance = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[] { iface }, InterfaceBasedExtension::invoke); - return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), - new Class[] { iface }, new InterceptingInvocationHandler(iface, target, beanManager)); + return beanManager.createInterceptionFactory(ctx, iface) + .createInterceptedInstance(instance); }); LOG.info("Registered bean for " + iface); }