From d6729a0bd53b85d7dc3177405a6da8724ec80bb5 Mon Sep 17 00:00:00 2001 From: Matej Novotny Date: Tue, 26 Sep 2023 11:37:22 +0200 Subject: [PATCH] WELD-2758 Proxies for non-public class-based beans should reside in bean's package if possible --- .../jboss/weld/bean/proxy/ProxyFactory.java | 9 ++++- ...yForInterceptedPackagePrivateBeanTest.java | 40 +++++++++++++++++++ .../classDefining/packPrivate/api/Alpha.java | 6 +++ .../packPrivate/impl/AlphaImpl.java | 20 ++++++++++ .../interceptor/MyInterceptor.java | 17 ++++++++ .../packPrivate/interceptor/SomeBinding.java | 11 +++++ 6 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/ProxyForInterceptedPackagePrivateBeanTest.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/api/Alpha.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/impl/AlphaImpl.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/interceptor/MyInterceptor.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/interceptor/SomeBinding.java diff --git a/impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java b/impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java index 8d9aabd898..4887679ff7 100644 --- a/impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java +++ b/impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java @@ -260,6 +260,13 @@ private static ProxyNameHolder createCompoundProxyName(String contextId, Bean } interfaces.add(mostSpecificClass.getSimpleName()); } + // if the bean class is a non-public one (i.e. pack private), we prioritize placing proxy in the same package + // we skip built-in beans are those are often for jakarta.* classes and end up in Weld's default package anyway + if (proxyPackage == null && bean != null + && !Modifier.isPublic(bean.getBeanClass().getModifiers()) + && !(bean instanceof AbstractBuiltInBean)) { + proxyPackage = bean.getBeanClass().getPackage().getName(); + } final Set declaringClasses = new HashSet<>(); for (Class type : typeInfo.getInterfaces()) { Class declaringClass = type.getDeclaringClass(); @@ -271,7 +278,7 @@ private static ProxyNameHolder createCompoundProxyName(String contextId, Bean proxyPackage = typeInfo.getPackageNameForClass(type); } } - // no need to sort the set, because we copied and already sorted one + // no need to sort the set, because we copied already sorted set Iterator iterator = interfaces.iterator(); while (iterator.hasNext()) { name.append(iterator.next()); diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/ProxyForInterceptedPackagePrivateBeanTest.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/ProxyForInterceptedPackagePrivateBeanTest.java new file mode 100644 index 0000000000..0e11d2ea23 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/ProxyForInterceptedPackagePrivateBeanTest.java @@ -0,0 +1,40 @@ +package org.jboss.weld.tests.classDefining.packPrivate; + +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.BeanArchive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.weld.test.util.Utils; +import org.jboss.weld.tests.classDefining.packPrivate.api.Alpha; +import org.jboss.weld.tests.classDefining.packPrivate.interceptor.MyInterceptor; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * See WELD-2758 + */ +@RunWith(Arquillian.class) +public class ProxyForInterceptedPackagePrivateBeanTest { + + @Deployment + public static Archive deploy() { + return ShrinkWrap + .create(BeanArchive.class, Utils.getDeploymentNameAsHash(ProxyForInterceptedPackagePrivateBeanTest.class)) + .addPackages(true, ProxyForInterceptedPackagePrivateBeanTest.class.getPackage()); + } + + @Inject + Instance instance; + + @Test + public void testProxyCanBeCreated() { + Instance select = instance.select(Alpha.class); + Assert.assertTrue(select.isResolvable()); + Assert.assertEquals(MyInterceptor.class.getSimpleName() + Alpha.class.getSimpleName(), select.get().ping()); + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/api/Alpha.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/api/Alpha.java new file mode 100644 index 0000000000..8a01addfc3 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/api/Alpha.java @@ -0,0 +1,6 @@ +package org.jboss.weld.tests.classDefining.packPrivate.api; + +public interface Alpha { + + String ping(); +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/impl/AlphaImpl.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/impl/AlphaImpl.java new file mode 100644 index 0000000000..77ca2f4c03 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/impl/AlphaImpl.java @@ -0,0 +1,20 @@ +package org.jboss.weld.tests.classDefining.packPrivate.impl; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Typed; + +import org.jboss.weld.tests.classDefining.packPrivate.api.Alpha; +import org.jboss.weld.tests.classDefining.packPrivate.interceptor.SomeBinding; + +/** + * Class is intentionally package private, @Typed to just the interface type and normal scoped to enforce client proxy + */ +@ApplicationScoped +@SomeBinding +@Typed(Alpha.class) +class AlphaImpl implements Alpha { + @Override + public String ping() { + return Alpha.class.getSimpleName(); + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/interceptor/MyInterceptor.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/interceptor/MyInterceptor.java new file mode 100644 index 0000000000..cf602a1d95 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/interceptor/MyInterceptor.java @@ -0,0 +1,17 @@ +package org.jboss.weld.tests.classDefining.packPrivate.interceptor; + +import jakarta.annotation.Priority; +import jakarta.interceptor.AroundInvoke; +import jakarta.interceptor.Interceptor; +import jakarta.interceptor.InvocationContext; + +@Interceptor +@SomeBinding +@Priority(Interceptor.Priority.APPLICATION) +public class MyInterceptor { + + @AroundInvoke + public Object intercept(InvocationContext context) throws Exception { + return this.getClass().getSimpleName() + context.proceed(); + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/interceptor/SomeBinding.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/interceptor/SomeBinding.java new file mode 100644 index 0000000000..d7ac933fa9 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/classDefining/packPrivate/interceptor/SomeBinding.java @@ -0,0 +1,11 @@ +package org.jboss.weld.tests.classDefining.packPrivate.interceptor; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import jakarta.interceptor.InterceptorBinding; + +@Retention(RetentionPolicy.RUNTIME) +@InterceptorBinding +public @interface SomeBinding { +}