Skip to content

Commit

Permalink
Veto REST Resources from CDI when constructors from Resources do not …
Browse files Browse the repository at this point in the history
…support CDI
  • Loading branch information
radcortez committed Jul 24, 2023
1 parent ab18d1b commit 6145732
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ public final class ResteasyDotNames {
public static final DotName PATH = DotName.createSimple("jakarta.ws.rs.Path");
public static final DotName DYNAMIC_FEATURE = DotName.createSimple("jakarta.ws.rs.container.DynamicFeature");
public static final DotName CONTEXT = DotName.createSimple("jakarta.ws.rs.core.Context");
public static final DotName PATH_PARAM = DotName.createSimple("jakarta.ws.rs.PathParam");
public static final DotName QUERY_PARAM = DotName.createSimple("jakarta.ws.rs.QueryParam");
public static final DotName HEADER_PARAM = DotName.createSimple("jakarta.ws.rs.HeaderParam");
public static final DotName FORM_PARAM = DotName.createSimple("jakarta.ws.rs.FormParam");
public static final DotName MATRIX_PARAM = DotName.createSimple("jakarta.ws.rs.MatrixParam");
public static final DotName COOKIE_PARAM = DotName.createSimple("jakarta.ws.rs.CookieParam");
public static final DotName RESTEASY_QUERY_PARAM = DotName
.createSimple("org.jboss.resteasy.annotations.jaxrs.QueryParam");
public static final DotName RESTEASY_FORM_PARAM = DotName
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package io.quarkus.resteasy.server.common.deployment;

import static io.quarkus.resteasy.common.spi.ResteasyDotNames.CONTEXT;
import static io.quarkus.resteasy.common.spi.ResteasyDotNames.COOKIE_PARAM;
import static io.quarkus.resteasy.common.spi.ResteasyDotNames.FORM_PARAM;
import static io.quarkus.resteasy.common.spi.ResteasyDotNames.HEADER_PARAM;
import static io.quarkus.resteasy.common.spi.ResteasyDotNames.MATRIX_PARAM;
import static io.quarkus.resteasy.common.spi.ResteasyDotNames.PATH_PARAM;
import static io.quarkus.resteasy.common.spi.ResteasyDotNames.QUERY_PARAM;
import static io.quarkus.runtime.annotations.ConfigPhase.BUILD_TIME;

import java.lang.reflect.InvocationTargetException;
Expand Down Expand Up @@ -422,6 +429,15 @@ public void build(

resteasyServerConfig.produce(new ResteasyServerConfigBuildItem(rootPath, path, resteasyInitParameters));

Set<DotName> restConstructorAnnotations = Set.of(
CONTEXT,
PATH_PARAM,
QUERY_PARAM,
HEADER_PARAM,
FORM_PARAM,
MATRIX_PARAM,
COOKIE_PARAM);

Set<DotName> autoInjectAnnotationNames = autoInjectAnnotations.stream().flatMap(a -> a.getAnnotationNames().stream())
.collect(Collectors.toSet());
annotationsTransformer.produce(new AnnotationsTransformerBuildItem(new AnnotationsTransformer() {
Expand All @@ -436,10 +452,34 @@ public void transform(TransformationContext context) {
ClassInfo clazz = context.getTarget().asClass();
if (clazz.declaredAnnotation(ResteasyDotNames.PATH) != null) {
// Root resources - no need to add scope, @Path is a bean defining annotation
Transformation transformation = context.transform();
if (clazz.declaredAnnotation(DotNames.TYPED) == null) {
// Add @Typed(MyResource.class)
context.transform().add(createTypedAnnotationInstance(clazz)).done();
transformation.add(createTypedAnnotationInstance(clazz));
}

// If we find a constructor with REST annotations it should be created by RESTEasy and not CDI, so we Veto
// https://issues.redhat.com/browse/RESTEASY-1538
// https://issues.redhat.com/browse/RESTEASY-2183
// https://github.com/jakartaee/rest/issues/633
// https://github.com/jakartaee/rest/issues/938
boolean restConstructorFound = false;
outer: for (MethodInfo constructor : clazz.constructors()) {
for (MethodParameterInfo parameter : constructor.parameters()) {
for (DotName paramAnnotation : restConstructorAnnotations) {
if (parameter.hasAnnotation(paramAnnotation)) {
restConstructorFound = true;
break outer;
}
}
}
}

if (restConstructorFound) {
transformation.add(DotNames.VETOED);
}

transformation.done();
return;
}
if (scopes.isScopeIn(context.getAnnotations())) {
Expand Down Expand Up @@ -472,6 +512,19 @@ public void transform(TransformationContext context) {
// Add @Typed(MySubresource.class)
transformation.add(createTypedAnnotationInstance(clazz));
}
// Force constructors with arguments to also include @Inject, because sub-resources can be managed by the user
if (!clazz.hasNoArgsConstructor()) {
boolean hasInject = false;
for (final MethodInfo constructor : clazz.constructors()) {
if (constructor.hasAnnotation(DotNames.INJECT)) {
hasInject = true;
break;
}
}
if (!hasInject) {
transformation.add(DotNames.VETOED);
}
}
transformation.done();
}
}
Expand Down Expand Up @@ -645,7 +698,7 @@ private static void registerProviders(ResteasyDeployment deployment,
ClassInfo classInfo = index.getClassByName(DotName.createSimple(providerToRegister));
boolean includeFields = false;
if (classInfo != null) {
includeFields = classInfo.annotationsMap().containsKey(ResteasyDotNames.CONTEXT);
includeFields = classInfo.annotationsMap().containsKey(CONTEXT);
}
reflectiveClass.produce(new ReflectiveClassBuildItem(false, includeFields, providerToRegister));
}
Expand Down Expand Up @@ -769,7 +822,7 @@ private static void checkParameterNames(IndexView index,
private static void registerContextProxyDefinitions(IndexView index,
BuildProducer<NativeImageProxyDefinitionBuildItem> proxyDefinition) {
// @Context uses proxies for interface injection
for (AnnotationInstance annotation : index.getAnnotations(ResteasyDotNames.CONTEXT)) {
for (AnnotationInstance annotation : index.getAnnotations(CONTEXT)) {
Type annotatedType = null;
if (annotation.target().kind() == AnnotationTarget.Kind.METHOD) {
MethodInfo method = annotation.target().asMethod();
Expand Down Expand Up @@ -870,7 +923,7 @@ private static void scanMethods(DotName annotationType,

for (short i = 0; i < method.parametersCount(); i++) {
Type parameterType = method.parameterType(i);
if (!hasAnnotation(method, i, ResteasyDotNames.CONTEXT)) {
if (!hasAnnotation(method, i, CONTEXT)) {
reflectiveHierarchy.produce(new ReflectiveHierarchyBuildItem.Builder()
.type(parameterType)
.index(index)
Expand Down

0 comments on commit 6145732

Please sign in to comment.