Skip to content

Commit cf0948c

Browse files
committed
Amazon Lambda - Support decorators
We need to ignore decorators and abstract classes when selecting the request handlers. Fixes #34824
1 parent 123ea8e commit cf0948c

File tree

3 files changed

+107
-4
lines changed

3 files changed

+107
-4
lines changed

extensions/amazon-lambda/deployment/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
<artifactId>rest-assured</artifactId>
3030
<scope>test</scope>
3131
</dependency>
32+
<dependency>
33+
<groupId>org.assertj</groupId>
34+
<artifactId>assertj-core</artifactId>
35+
<scope>test</scope>
36+
</dependency>
3237

3338
<dependency>
3439
<groupId>io.quarkus</groupId>

extensions/amazon-lambda/deployment/src/main/java/io/quarkus/amazon/lambda/deployment/AmazonLambdaProcessor.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
import java.lang.reflect.Method;
44
import java.lang.reflect.Modifier;
55
import java.util.ArrayList;
6-
import java.util.Collection;
76
import java.util.Collections;
87
import java.util.HashMap;
98
import java.util.List;
109
import java.util.Map;
1110
import java.util.Optional;
1211
import java.util.Set;
12+
import java.util.function.Predicate;
1313

1414
import jakarta.inject.Named;
1515

@@ -29,6 +29,7 @@
2929
import io.quarkus.amazon.lambda.runtime.LambdaBuildTimeConfig;
3030
import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
3131
import io.quarkus.arc.deployment.BeanContainerBuildItem;
32+
import io.quarkus.arc.processor.DotNames;
3233
import io.quarkus.builder.BuildException;
3334
import io.quarkus.deployment.Feature;
3435
import io.quarkus.deployment.annotations.BuildProducer;
@@ -58,6 +59,18 @@ public final class AmazonLambdaProcessor {
5859
private static final DotName NAMED = DotName.createSimple(Named.class.getName());
5960
private static final Logger log = Logger.getLogger(AmazonLambdaProcessor.class);
6061

62+
private static final Predicate<ClassInfo> INCLUDE_HANDLER_PREDICATE = new Predicate<>() {
63+
64+
@Override
65+
public boolean test(ClassInfo classInfo) {
66+
if (classInfo.isAbstract() || classInfo.hasAnnotation(DotNames.DECORATOR)) {
67+
return false;
68+
}
69+
70+
return true;
71+
}
72+
};
73+
6174
@BuildStep
6275
FeatureBuildItem feature() {
6376
return new FeatureBuildItem(Feature.AMAZON_LAMBDA);
@@ -75,11 +88,13 @@ List<AmazonLambdaBuildItem> discover(CombinedIndexBuildItem combinedIndexBuildIt
7588
BuildProducer<ReflectiveHierarchyBuildItem> reflectiveHierarchy,
7689
BuildProducer<ReflectiveClassBuildItem> reflectiveClassBuildItemBuildProducer) throws BuildException {
7790

78-
Collection<ClassInfo> allKnownImplementors = combinedIndexBuildItem.getIndex().getAllKnownImplementors(REQUEST_HANDLER);
91+
List<ClassInfo> allKnownImplementors = new ArrayList<>(
92+
combinedIndexBuildItem.getIndex().getAllKnownImplementors(REQUEST_HANDLER)
93+
.stream().filter(INCLUDE_HANDLER_PREDICATE).toList());
7994
allKnownImplementors.addAll(combinedIndexBuildItem.getIndex()
80-
.getAllKnownImplementors(REQUEST_STREAM_HANDLER));
95+
.getAllKnownImplementors(REQUEST_STREAM_HANDLER).stream().filter(INCLUDE_HANDLER_PREDICATE).toList());
8196
allKnownImplementors.addAll(combinedIndexBuildItem.getIndex()
82-
.getAllKnownSubclasses(SKILL_STREAM_HANDLER));
97+
.getAllKnownSubclasses(SKILL_STREAM_HANDLER).stream().filter(INCLUDE_HANDLER_PREDICATE).toList());
8398

8499
if (allKnownImplementors.size() > 0 && providedLambda.isPresent()) {
85100
throw new BuildException(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package io.quarkus.amazon.lambda.deployment.testing;
2+
3+
import static io.restassured.RestAssured.given;
4+
import static org.assertj.core.api.Assertions.assertThat;
5+
import static org.hamcrest.CoreMatchers.containsString;
6+
7+
import java.util.logging.Level;
8+
import java.util.logging.LogRecord;
9+
10+
import jakarta.annotation.Priority;
11+
import jakarta.decorator.Decorator;
12+
import jakarta.decorator.Delegate;
13+
import jakarta.enterprise.inject.Any;
14+
import jakarta.inject.Inject;
15+
16+
import org.jboss.logging.Logger;
17+
import org.jboss.shrinkwrap.api.ShrinkWrap;
18+
import org.jboss.shrinkwrap.api.spec.JavaArchive;
19+
import org.junit.jupiter.api.Test;
20+
import org.junit.jupiter.api.extension.RegisterExtension;
21+
22+
import com.amazonaws.services.lambda.runtime.Context;
23+
import com.amazonaws.services.lambda.runtime.RequestHandler;
24+
25+
import io.quarkus.amazon.lambda.deployment.testing.model.InputPerson;
26+
import io.quarkus.test.QuarkusUnitTest;
27+
28+
class LambdaWithDecoratorTest {
29+
30+
@RegisterExtension
31+
static final QuarkusUnitTest test = new QuarkusUnitTest().setArchiveProducer(() -> ShrinkWrap
32+
.create(JavaArchive.class)
33+
.addClasses(LambdaWithDecorator.class, RequestHandlerDecorator.class, InputPerson.class))
34+
.setLogRecordPredicate(record -> record.getLevel().intValue() == Level.INFO.intValue()
35+
&& record.getMessage().contains("handling request with id"))
36+
.assertLogRecords(records -> assertThat(records)
37+
.extracting(LogRecord::getMessage)
38+
.isNotEmpty());
39+
40+
@Test
41+
public void testLambdaWithDecorator() throws Exception {
42+
// you test your lambdas by invoking on http://localhost:8081
43+
// this works in dev mode too
44+
45+
InputPerson in = new InputPerson("Stu");
46+
given()
47+
.contentType("application/json")
48+
.accept("application/json")
49+
.body(in)
50+
.when()
51+
.post()
52+
.then()
53+
.statusCode(200)
54+
.body(containsString("Hey Stu"));
55+
}
56+
57+
public static class LambdaWithDecorator implements RequestHandler<InputPerson, String> {
58+
59+
@Override
60+
public String handleRequest(InputPerson input, Context context) {
61+
return "Hey " + input.getName();
62+
}
63+
}
64+
65+
@Priority(10)
66+
@Decorator
67+
public static class RequestHandlerDecorator<I, O> implements RequestHandler<I, O> {
68+
69+
@Inject
70+
Logger logger;
71+
72+
@Inject
73+
@Any
74+
@Delegate
75+
RequestHandler<I, O> delegate;
76+
77+
@Override
78+
public O handleRequest(I i, Context context) {
79+
logger.info("handling request with id " + context.getAwsRequestId());
80+
return delegate.handleRequest(i, context);
81+
}
82+
}
83+
}

0 commit comments

Comments
 (0)