diff --git a/extensions/amazon-lambda/deployment/pom.xml b/extensions/amazon-lambda/deployment/pom.xml
index 24060850709a8a..083bdd130e5319 100644
--- a/extensions/amazon-lambda/deployment/pom.xml
+++ b/extensions/amazon-lambda/deployment/pom.xml
@@ -29,6 +29,11 @@
rest-assured
test
+
+ org.assertj
+ assertj-core
+ test
+
io.quarkus
diff --git a/extensions/amazon-lambda/deployment/src/main/java/io/quarkus/amazon/lambda/deployment/AmazonLambdaProcessor.java b/extensions/amazon-lambda/deployment/src/main/java/io/quarkus/amazon/lambda/deployment/AmazonLambdaProcessor.java
index 33d9a166154822..d7b631b826e24a 100644
--- a/extensions/amazon-lambda/deployment/src/main/java/io/quarkus/amazon/lambda/deployment/AmazonLambdaProcessor.java
+++ b/extensions/amazon-lambda/deployment/src/main/java/io/quarkus/amazon/lambda/deployment/AmazonLambdaProcessor.java
@@ -3,13 +3,13 @@
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.function.Predicate;
import jakarta.inject.Named;
@@ -29,6 +29,7 @@
import io.quarkus.amazon.lambda.runtime.LambdaBuildTimeConfig;
import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.arc.deployment.BeanContainerBuildItem;
+import io.quarkus.arc.processor.DotNames;
import io.quarkus.builder.BuildException;
import io.quarkus.deployment.Feature;
import io.quarkus.deployment.annotations.BuildProducer;
@@ -58,6 +59,18 @@ public final class AmazonLambdaProcessor {
private static final DotName NAMED = DotName.createSimple(Named.class.getName());
private static final Logger log = Logger.getLogger(AmazonLambdaProcessor.class);
+ private static final Predicate INCLUDE_HANDLER_PREDICATE = new Predicate<>() {
+
+ @Override
+ public boolean test(ClassInfo classInfo) {
+ if (classInfo.isAbstract() || classInfo.hasAnnotation(DotNames.DECORATOR)) {
+ return false;
+ }
+
+ return true;
+ }
+ };
+
@BuildStep
FeatureBuildItem feature() {
return new FeatureBuildItem(Feature.AMAZON_LAMBDA);
@@ -75,11 +88,13 @@ List discover(CombinedIndexBuildItem combinedIndexBuildIt
BuildProducer reflectiveHierarchy,
BuildProducer reflectiveClassBuildItemBuildProducer) throws BuildException {
- Collection allKnownImplementors = combinedIndexBuildItem.getIndex().getAllKnownImplementors(REQUEST_HANDLER);
+ List allKnownImplementors = new ArrayList<>(
+ combinedIndexBuildItem.getIndex().getAllKnownImplementors(REQUEST_HANDLER)
+ .stream().filter(INCLUDE_HANDLER_PREDICATE).toList());
allKnownImplementors.addAll(combinedIndexBuildItem.getIndex()
- .getAllKnownImplementors(REQUEST_STREAM_HANDLER));
+ .getAllKnownImplementors(REQUEST_STREAM_HANDLER).stream().filter(INCLUDE_HANDLER_PREDICATE).toList());
allKnownImplementors.addAll(combinedIndexBuildItem.getIndex()
- .getAllKnownSubclasses(SKILL_STREAM_HANDLER));
+ .getAllKnownSubclasses(SKILL_STREAM_HANDLER).stream().filter(INCLUDE_HANDLER_PREDICATE).toList());
if (allKnownImplementors.size() > 0 && providedLambda.isPresent()) {
throw new BuildException(
diff --git a/extensions/amazon-lambda/deployment/src/test/java/io/quarkus/amazon/lambda/deployment/testing/LambdaWithDecoratorTest.java b/extensions/amazon-lambda/deployment/src/test/java/io/quarkus/amazon/lambda/deployment/testing/LambdaWithDecoratorTest.java
new file mode 100644
index 00000000000000..e1c286131eb58c
--- /dev/null
+++ b/extensions/amazon-lambda/deployment/src/test/java/io/quarkus/amazon/lambda/deployment/testing/LambdaWithDecoratorTest.java
@@ -0,0 +1,83 @@
+package io.quarkus.amazon.lambda.deployment.testing;
+
+import static io.restassured.RestAssured.given;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.CoreMatchers.containsString;
+
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+import jakarta.annotation.Priority;
+import jakarta.decorator.Decorator;
+import jakarta.decorator.Delegate;
+import jakarta.enterprise.inject.Any;
+import jakarta.inject.Inject;
+
+import org.jboss.logging.Logger;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.RequestHandler;
+
+import io.quarkus.amazon.lambda.deployment.testing.model.InputPerson;
+import io.quarkus.test.QuarkusUnitTest;
+
+class LambdaWithDecoratorTest {
+
+ @RegisterExtension
+ static final QuarkusUnitTest test = new QuarkusUnitTest().setArchiveProducer(() -> ShrinkWrap
+ .create(JavaArchive.class)
+ .addClasses(LambdaWithDecorator.class, RequestHandlerDecorator.class, InputPerson.class))
+ .setLogRecordPredicate(record -> record.getLevel().intValue() == Level.INFO.intValue()
+ && record.getMessage().contains("handling request with id"))
+ .assertLogRecords(records -> assertThat(records)
+ .extracting(LogRecord::getMessage)
+ .isNotEmpty());
+
+ @Test
+ public void testLambdaWithDecorator() throws Exception {
+ // you test your lambdas by invoking on http://localhost:8081
+ // this works in dev mode too
+
+ InputPerson in = new InputPerson("Stu");
+ given()
+ .contentType("application/json")
+ .accept("application/json")
+ .body(in)
+ .when()
+ .post()
+ .then()
+ .statusCode(200)
+ .body(containsString("Hey Stu"));
+ }
+
+ public static class LambdaWithDecorator implements RequestHandler {
+
+ @Override
+ public String handleRequest(InputPerson input, Context context) {
+ return "Hey " + input.getName();
+ }
+ }
+
+ @Priority(10)
+ @Decorator
+ public static class RequestHandlerDecorator implements RequestHandler {
+
+ @Inject
+ Logger logger;
+
+ @Inject
+ @Any
+ @Delegate
+ RequestHandler delegate;
+
+ @Override
+ public O handleRequest(I i, Context context) {
+ logger.info("handling request with id " + context.getAwsRequestId());
+ return delegate.handleRequest(i, context);
+ }
+ }
+}