diff --git a/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/decorator/DecoratorOfExternalBeanTest.java b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/decorator/DecoratorOfExternalBeanTest.java
new file mode 100644
index 0000000000000..8a166fb63c248
--- /dev/null
+++ b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/decorator/DecoratorOfExternalBeanTest.java
@@ -0,0 +1,49 @@
+package io.quarkus.arc.test.decorator;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.List;
+
+import jakarta.decorator.Decorator;
+import jakarta.decorator.Delegate;
+import jakarta.inject.Inject;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.quarkus.arc.test.supplement.SomeBeanInExternalLibrary;
+import io.quarkus.arc.test.supplement.SomeInterfaceInExternalLibrary;
+import io.quarkus.builder.Version;
+import io.quarkus.maven.dependency.Dependency;
+import io.quarkus.test.QuarkusUnitTest;
+
+public class DecoratorOfExternalBeanTest {
+ // the test includes an _application_ decorator (in the Runtime CL) that applies
+ // to a bean that is _outside_ of the application (in the Base Runtime CL)
+
+ @RegisterExtension
+ static final QuarkusUnitTest config = new QuarkusUnitTest()
+ .withApplicationRoot(jar -> jar.addClass(MyDecorator.class))
+ // we need a non-application archive, so cannot use `withAdditionalDependency()`
+ .setForcedDependencies(List.of(Dependency.of("io.quarkus", "quarkus-arc-test-supplement", Version.getVersion())));
+
+ @Inject
+ SomeBeanInExternalLibrary bean;
+
+ @Test
+ public void test() {
+ assertEquals("Delegated: Hello", bean.hello());
+ }
+
+ @Decorator
+ public static class MyDecorator implements SomeInterfaceInExternalLibrary {
+ @Inject
+ @Delegate
+ SomeInterfaceInExternalLibrary delegate;
+
+ @Override
+ public String hello() {
+ return "Delegated: " + delegate.hello();
+ }
+ }
+}
diff --git a/extensions/arc/test-supplement/pom.xml b/extensions/arc/test-supplement/pom.xml
index 0f40b77893883..4f9e04eb3b135 100644
--- a/extensions/arc/test-supplement/pom.xml
+++ b/extensions/arc/test-supplement/pom.xml
@@ -13,4 +13,11 @@
Quarkus - ArC - Test Supplement
Supplement archive for ArC tests
+
+
+ jakarta.enterprise
+ jakarta.enterprise.cdi-api
+
+
+
diff --git a/extensions/arc/test-supplement/src/main/java/io/quarkus/arc/test/supplement/SomeBeanInExternalLibrary.java b/extensions/arc/test-supplement/src/main/java/io/quarkus/arc/test/supplement/SomeBeanInExternalLibrary.java
new file mode 100644
index 0000000000000..1e722755fa73c
--- /dev/null
+++ b/extensions/arc/test-supplement/src/main/java/io/quarkus/arc/test/supplement/SomeBeanInExternalLibrary.java
@@ -0,0 +1,11 @@
+package io.quarkus.arc.test.supplement;
+
+import jakarta.enterprise.context.Dependent;
+
+@Dependent
+public class SomeBeanInExternalLibrary implements SomeInterfaceInExternalLibrary {
+ @Override
+ public String hello() {
+ return "Hello";
+ }
+}
diff --git a/extensions/arc/test-supplement/src/main/java/io/quarkus/arc/test/supplement/SomeInterfaceInExternalLibrary.java b/extensions/arc/test-supplement/src/main/java/io/quarkus/arc/test/supplement/SomeInterfaceInExternalLibrary.java
new file mode 100644
index 0000000000000..f621a3c9d27a0
--- /dev/null
+++ b/extensions/arc/test-supplement/src/main/java/io/quarkus/arc/test/supplement/SomeInterfaceInExternalLibrary.java
@@ -0,0 +1,5 @@
+package io.quarkus.arc.test.supplement;
+
+public interface SomeInterfaceInExternalLibrary {
+ String hello();
+}
diff --git a/extensions/arc/test-supplement/src/main/resources/META-INF/beans.xml b/extensions/arc/test-supplement/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java
index da197f726362b..7b763b4f47fb3 100644
--- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java
+++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java
@@ -344,7 +344,9 @@ Collection generateClassBean(BeanInfo bean, ClassInfo beanClass) {
return Collections.emptyList();
}
- boolean isApplicationClass = applicationClassPredicate.test(beanClass.name()) || bean.isForceApplicationClass();
+ boolean isApplicationClass = applicationClassPredicate.test(beanClass.name())
+ || bean.isForceApplicationClass()
+ || bean.hasBoundDecoratorWhichIsApplicationClass(applicationClassPredicate);
ResourceClassOutput classOutput = new ResourceClassOutput(isApplicationClass,
name -> name.equals(generatedName) ? SpecialType.BEAN : null, generateSources);
diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java
index 8b3d1ceca018d..89e964f9cab17 100644
--- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java
+++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java
@@ -18,6 +18,7 @@
import java.util.OptionalInt;
import java.util.Set;
import java.util.function.Consumer;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
import jakarta.enterprise.inject.Typed;
@@ -514,6 +515,15 @@ public List getBoundDecorators() {
return bound;
}
+ boolean hasBoundDecoratorWhichIsApplicationClass(Predicate isApplicationClass) {
+ for (DecoratorInfo decorator : getBoundDecorators()) {
+ if (isApplicationClass.test(decorator.getImplClazz().name())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
*
* @return the list of around invoke interceptor methods declared in the hierarchy of a bean class
diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ClientProxyGenerator.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ClientProxyGenerator.java
index b7c262df9af8b..f5c64a88e4691 100644
--- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ClientProxyGenerator.java
+++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ClientProxyGenerator.java
@@ -98,8 +98,9 @@ Collection generate(BeanInfo bean, String beanClassName,
return Collections.emptyList();
}
- boolean applicationClass = applicationClassPredicate.test(getApplicationClassTestName(bean));
- ResourceClassOutput classOutput = new ResourceClassOutput(applicationClass,
+ boolean isApplicationClass = applicationClassPredicate.test(getApplicationClassTestName(bean))
+ || bean.hasBoundDecoratorWhichIsApplicationClass(applicationClassPredicate);
+ ResourceClassOutput classOutput = new ResourceClassOutput(isApplicationClass,
name -> name.equals(generatedName) ? SpecialType.CLIENT_PROXY : null, generateSources);
// Foo_ClientProxy extends Foo implements ClientProxy
diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/SubclassGenerator.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/SubclassGenerator.java
index b14ee140c82b4..23ad18173f797 100644
--- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/SubclassGenerator.java
+++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/SubclassGenerator.java
@@ -112,7 +112,9 @@ Collection generate(BeanInfo bean, String beanClassName) {
return Collections.emptyList();
}
- ResourceClassOutput classOutput = new ResourceClassOutput(applicationClassPredicate.test(bean.getBeanClass()),
+ boolean isApplicationClass = applicationClassPredicate.test(bean.getBeanClass())
+ || bean.hasBoundDecoratorWhichIsApplicationClass(applicationClassPredicate);
+ ResourceClassOutput classOutput = new ResourceClassOutput(isApplicationClass,
name -> name.equals(generatedName) ? SpecialType.SUBCLASS : null,
generateSources);