Skip to content

Commit

Permalink
ArC client proxies - prioritize delegating methods impl. on superclasses
Browse files Browse the repository at this point in the history
- resolves quarkusio#17755

(cherry picked from commit a761ecd)
  • Loading branch information
mkouba authored and gsmet committed Jun 10, 2021
1 parent fa37549 commit 279d445
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.FieldInfo;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.Type;
import org.jboss.jandex.TypeVariable;
Expand Down Expand Up @@ -310,11 +311,12 @@ void implementGetBean(ClassCreator clientProxy, FieldDescriptor beanField) {
Collection<MethodInfo> getDelegatingMethods(BeanInfo bean, Consumer<BytecodeTransformer> bytecodeTransformerConsumer,
boolean transformUnproxyableClasses) {
Map<Methods.MethodKey, MethodInfo> methods = new HashMap<>();
IndexView index = bean.getDeployment().getBeanArchiveIndex();

if (bean.isClassBean()) {
Set<Methods.NameAndDescriptor> methodsFromWhichToRemoveFinal = new HashSet<>();
ClassInfo classInfo = bean.getTarget().get().asClass();
Methods.addDelegatingMethods(bean.getDeployment().getBeanArchiveIndex(), classInfo,
Methods.addDelegatingMethods(index, classInfo,
methods, methodsFromWhichToRemoveFinal, transformUnproxyableClasses);
if (!methodsFromWhichToRemoveFinal.isEmpty()) {
String className = classInfo.name().toString();
Expand All @@ -323,16 +325,16 @@ Collection<MethodInfo> getDelegatingMethods(BeanInfo bean, Consumer<BytecodeTran
}
} else if (bean.isProducerMethod()) {
MethodInfo producerMethod = bean.getTarget().get().asMethod();
ClassInfo returnTypeClass = getClassByName(bean.getDeployment().getBeanArchiveIndex(), producerMethod.returnType());
Methods.addDelegatingMethods(bean.getDeployment().getBeanArchiveIndex(), returnTypeClass, methods, null,
ClassInfo returnTypeClass = getClassByName(index, producerMethod.returnType());
Methods.addDelegatingMethods(index, returnTypeClass, methods, null,
transformUnproxyableClasses);
} else if (bean.isProducerField()) {
FieldInfo producerField = bean.getTarget().get().asField();
ClassInfo fieldClass = getClassByName(bean.getDeployment().getBeanArchiveIndex(), producerField.type());
Methods.addDelegatingMethods(bean.getDeployment().getBeanArchiveIndex(), fieldClass, methods, null,
ClassInfo fieldClass = getClassByName(index, producerField.type());
Methods.addDelegatingMethods(index, fieldClass, methods, null,
transformUnproxyableClasses);
} else if (bean.isSynthetic()) {
Methods.addDelegatingMethods(bean.getDeployment().getBeanArchiveIndex(), bean.getImplClazz(), methods, null,
Methods.addDelegatingMethods(index, bean.getImplClazz(), methods, null,
transformUnproxyableClasses);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ static boolean isBridge(MethodInfo method) {

static void addDelegatingMethods(IndexView index, ClassInfo classInfo, Map<MethodKey, MethodInfo> methods,
Set<NameAndDescriptor> methodsFromWhichToRemoveFinal, boolean transformUnproxyableClasses) {
// TODO support interfaces default methods
if (classInfo != null) {
// First methods declared on the class
for (MethodInfo method : classInfo.methods()) {
if (skipForClientProxy(method, transformUnproxyableClasses, methodsFromWhichToRemoveFinal)) {
continue;
Expand All @@ -88,21 +88,23 @@ static void addDelegatingMethods(IndexView index, ClassInfo classInfo, Map<Metho
key.method.exceptions().toArray(Type.EMPTY_ARRAY));
});
}
// Interfaces
for (Type interfaceType : classInfo.interfaceTypes()) {
ClassInfo interfaceClassInfo = getClassByName(index, interfaceType.name());
if (interfaceClassInfo != null) {
addDelegatingMethods(index, interfaceClassInfo, methods, methodsFromWhichToRemoveFinal,
transformUnproxyableClasses);
}
}
// Methods declared on superclasses
if (classInfo.superClassType() != null) {
ClassInfo superClassInfo = getClassByName(index, classInfo.superName());
if (superClassInfo != null) {
addDelegatingMethods(index, superClassInfo, methods, methodsFromWhichToRemoveFinal,
transformUnproxyableClasses);
}
}
// Methods declared on implemented interfaces
// TODO support interfaces default methods
for (DotName interfaceName : classInfo.interfaceNames()) {
ClassInfo interfaceClassInfo = getClassByName(index, interfaceName);
if (interfaceClassInfo != null) {
addDelegatingMethods(index, interfaceClassInfo, methods, methodsFromWhichToRemoveFinal,
transformUnproxyableClasses);
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.quarkus.arc.test.clientproxy.delegatingmethods;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import io.quarkus.arc.Arc;
import io.quarkus.arc.ClientProxy;
import io.quarkus.arc.test.ArcTestContainer;
import java.io.IOException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

public class ClientProxyMethodInvocationInConstructorTest {

@RegisterExtension
public ArcTestContainer container = new ArcTestContainer(MyBean.class, Component.class, HasElement.class, HasSize.class);

@Test
public void testClientProxy() throws IOException {
// Just test that the client proxy can be instantiated
MyBean myBean = Arc.container().instance(MyBean.class).get();
assertTrue(myBean instanceof ClientProxy);
assertEquals("an element", myBean.getElement().toString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.quarkus.arc.test.clientproxy.delegatingmethods;

public class Component implements HasElement {

private static final long serialVersionUID = 1L;

@Override
public Object getElement() {
return "an element";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.quarkus.arc.test.clientproxy.delegatingmethods;

import java.io.Serializable;

@FunctionalInterface
public interface HasElement extends Serializable {

Object getElement();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.quarkus.arc.test.clientproxy.delegatingmethods;

public interface HasSize extends HasElement {

default void setSize(String size) {
getElement();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.quarkus.arc.test.clientproxy.delegatingmethods;

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class MyBean extends Component implements HasSize {

private static final long serialVersionUID = 1L;

public MyBean() {
setSize("5px");
}

}

0 comments on commit 279d445

Please sign in to comment.