diff --git a/samples/springboot3/graphql-pet-store/README.md b/samples/springboot3/graphql-pet-store/README.md
new file mode 100644
index 000000000..e5bfad120
--- /dev/null
+++ b/samples/springboot3/graphql-pet-store/README.md
@@ -0,0 +1,38 @@
+# Serverless Spring Boot 3 with GraphQL example
+A basic pet store written with the [Spring Boot 3 framework](https://projects.spring.io/spring-boot/). Unlike older examples, this example uses the [Spring for GraphQl](https://docs.spring.io/spring-graphql/reference/) library.
+
+
+The application can be deployed in an AWS account using the [Serverless Application Model](https://github.com/awslabs/serverless-application-model). The `template.yml` file in the root folder contains the application definition.
+
+## Pre-requisites
+* [AWS CLI](https://aws.amazon.com/cli/)
+* [SAM CLI](https://github.com/awslabs/aws-sam-cli)
+* [Gradle](https://gradle.org/) or [Maven](https://maven.apache.org/)
+
+## Deployment
+In a shell, navigate to the sample's folder and use the SAM CLI to build a deployable package
+```
+$ sam build
+```
+
+This command compiles the application and prepares a deployment package in the `.aws-sam` sub-directory.
+
+To deploy the application in your AWS account, you can use the SAM CLI's guided deployment process and follow the instructions on the screen
+
+```
+$ sam deploy --guided
+```
+
+Once the deployment is completed, the SAM CLI will print out the stack's outputs, including the new application URL. You can use `curl` to make a call to the URL
+
+```
+...
+---------------------------------------------------------------------------------------------------------
+OutputKey-Description OutputValue
+---------------------------------------------------------------------------------------------------------
+PetStoreApi - URL for application https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/graphQl
+---------------------------------------------------------------------------------------------------------
+
+$ curl -X POST https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/graphQl -d '{"query":"query petDetails {\n petById(id: \"pet-1\") {\n id\n name\n breed\n owner {\n id\n firstName\n lastName\n }\n }\n}","operationName":"petDetails"}' -H "Content-Type: application/json"
+
+```
\ No newline at end of file
diff --git a/samples/springboot3/graphql-pet-store/pom.xml b/samples/springboot3/graphql-pet-store/pom.xml
new file mode 100644
index 000000000..35535e2a4
--- /dev/null
+++ b/samples/springboot3/graphql-pet-store/pom.xml
@@ -0,0 +1,162 @@
+
+
+ 4.0.0
+
+ com.amazonaws.serverless.sample
+ serverless-springboot3-example
+ 2.0-SNAPSHOT
+ Spring Boot example for the aws-serverless-java-container library
+ Simple pet store written with the Spring framework and Spring Boot
+ https://aws.amazon.com/lambda/
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.2
+
+
+
+
+ The Apache Software License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+ repo
+
+
+
+
+ 21
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-graphql
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+
+
+
+
+ org.springframework.graphql
+ spring-graphql-test
+ test
+
+
+ com.amazonaws.serverless
+ aws-serverless-java-container-springboot3
+ 2.0.0-SNAPSHOT
+
+
+
+
+
+ shaded-jar
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.5.1
+
+ false
+
+
+
+ package
+
+ shade
+
+
+
+
+ org.apache.tomcat.embed:*
+
+
+
+
+
+
+
+
+
+
+ assembly-zip
+
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.3.0
+
+
+ default-jar
+ none
+
+
+
+
+ org.apache.maven.plugins
+ maven-install-plugin
+ 3.1.1
+
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ 3.6.1
+
+
+ copy-dependencies
+ package
+
+ copy-dependencies
+
+
+ ${project.build.directory}/lib
+ runtime
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 3.6.0
+
+
+ zip-assembly
+ package
+
+ single
+
+
+ ${project.artifactId}-${project.version}
+
+ src${file.separator}assembly${file.separator}bin.xml
+
+ false
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/springboot3/graphql-pet-store/src/assembly/bin.xml b/samples/springboot3/graphql-pet-store/src/assembly/bin.xml
new file mode 100644
index 000000000..efc312c25
--- /dev/null
+++ b/samples/springboot3/graphql-pet-store/src/assembly/bin.xml
@@ -0,0 +1,27 @@
+
+ lambda-package
+
+ zip
+
+ false
+
+
+
+ ${project.build.directory}${file.separator}lib
+ lib
+
+ tomcat-embed*
+
+
+
+
+ ${project.build.directory}${file.separator}classes
+
+ **
+
+ ${file.separator}
+
+
+
diff --git a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/Application.java b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/Application.java
new file mode 100644
index 000000000..9cf0ea610
--- /dev/null
+++ b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/Application.java
@@ -0,0 +1,43 @@
+package com.amazonaws.serverless.sample.springboot3;
+
+import com.amazonaws.serverless.sample.springboot3.controller.PetsController;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Import;
+import org.springframework.web.servlet.HandlerAdapter;
+import org.springframework.web.servlet.HandlerMapping;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+
+
+@SpringBootApplication
+@Import({ PetsController.class })
+public class Application {
+
+ // silence console logging
+ @Value("${logging.level.root:OFF}")
+ String message = "";
+
+ /*
+ * Create required HandlerMapping, to avoid several default HandlerMapping instances being created
+ */
+ @Bean
+ public HandlerMapping handlerMapping() {
+ return new RequestMappingHandlerMapping();
+ }
+
+ /*
+ * Create required HandlerAdapter, to avoid several default HandlerAdapter instances being created
+ */
+ @Bean
+ public HandlerAdapter handlerAdapter() {
+ return new RequestMappingHandlerAdapter();
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/StreamLambdaHandler.java b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/StreamLambdaHandler.java
new file mode 100644
index 000000000..a65c6f1ec
--- /dev/null
+++ b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/StreamLambdaHandler.java
@@ -0,0 +1,50 @@
+package com.amazonaws.serverless.sample.springboot3;
+
+
+import com.amazonaws.serverless.exceptions.ContainerInitializationException;
+import com.amazonaws.serverless.proxy.internal.testutils.Timer;
+import com.amazonaws.serverless.proxy.model.AwsProxyRequest;
+import com.amazonaws.serverless.proxy.model.AwsProxyResponse;
+import com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler;
+import com.amazonaws.serverless.sample.springboot3.filter.CognitoIdentityFilter;
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
+
+import jakarta.servlet.DispatcherType;
+import jakarta.servlet.FilterRegistration;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.EnumSet;
+
+
+public class StreamLambdaHandler implements RequestStreamHandler {
+ private static SpringBootLambdaContainerHandler handler;
+ static {
+ try {
+ handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(Application.class);
+
+ // we use the onStartup method of the handler to register our custom filter
+ handler.onStartup(servletContext -> {
+ FilterRegistration.Dynamic registration = servletContext.addFilter("CognitoIdentityFilter", CognitoIdentityFilter.class);
+ registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
+ });
+ } catch (ContainerInitializationException e) {
+ // if we fail here. We re-throw the exception to force another cold start
+ e.printStackTrace();
+ throw new RuntimeException("Could not initialize Spring Boot application", e);
+ }
+ }
+
+ public StreamLambdaHandler() {
+ // we enable the timer for debugging. This SHOULD NOT be enabled in production.
+ Timer.enable();
+ }
+
+ @Override
+ public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context)
+ throws IOException {
+ handler.proxyStream(inputStream, outputStream, context);
+ }
+}
diff --git a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/controller/PetsController.java b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/controller/PetsController.java
new file mode 100644
index 000000000..93eb999bd
--- /dev/null
+++ b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/controller/PetsController.java
@@ -0,0 +1,21 @@
+package com.amazonaws.serverless.sample.springboot3.controller;
+
+import org.springframework.graphql.data.method.annotation.Argument;
+import org.springframework.graphql.data.method.annotation.QueryMapping;
+import org.springframework.graphql.data.method.annotation.SchemaMapping;
+import org.springframework.stereotype.Controller;
+import com.amazonaws.serverless.sample.springboot3.model.Owner;
+import com.amazonaws.serverless.sample.springboot3.model.Pet;
+
+@Controller
+public class PetsController {
+ @QueryMapping
+ public Pet petById(@Argument String id) {
+ return Pet.getById(id);
+ }
+
+ @SchemaMapping
+ public Owner owner(Pet pet) {
+ return Owner.getById(pet.ownerId());
+ }
+}
diff --git a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/filter/CognitoIdentityFilter.java b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/filter/CognitoIdentityFilter.java
new file mode 100644
index 000000000..d6ccae765
--- /dev/null
+++ b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/filter/CognitoIdentityFilter.java
@@ -0,0 +1,69 @@
+package com.amazonaws.serverless.sample.springboot3.filter;
+
+
+import com.amazonaws.serverless.proxy.RequestReader;
+import com.amazonaws.serverless.proxy.model.AwsProxyRequestContext;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+
+import java.io.IOException;
+
+
+/**
+ * Simple Filter implementation that looks for a Cognito identity id in the API Gateway request context
+ * and stores the value in a request attribute. The filter is registered with aws-serverless-java-container
+ * in the onStartup method from the {@link com.amazonaws.serverless.sample.springboot3.StreamLambdaHandler} class.
+ */
+public class CognitoIdentityFilter implements Filter {
+ public static final String COGNITO_IDENTITY_ATTRIBUTE = "com.amazonaws.serverless.cognitoId";
+
+ private static Logger log = LoggerFactory.getLogger(CognitoIdentityFilter.class);
+
+ @Override
+ public void init(FilterConfig filterConfig)
+ throws ServletException {
+ // nothing to do in init
+ }
+
+
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
+ throws IOException, ServletException {
+ Object apiGwContext = servletRequest.getAttribute(RequestReader.API_GATEWAY_CONTEXT_PROPERTY);
+ if (apiGwContext == null) {
+ log.warn("API Gateway context is null");
+ filterChain.doFilter(servletRequest, servletResponse);
+ return;
+ }
+ if (!AwsProxyRequestContext.class.isAssignableFrom(apiGwContext.getClass())) {
+ log.warn("API Gateway context object is not of valid type");
+ filterChain.doFilter(servletRequest, servletResponse);
+ }
+
+ AwsProxyRequestContext ctx = (AwsProxyRequestContext)apiGwContext;
+ if (ctx.getIdentity() == null) {
+ log.warn("Identity context is null");
+ filterChain.doFilter(servletRequest, servletResponse);
+ }
+ String cognitoIdentityId = ctx.getIdentity().getCognitoIdentityId();
+ if (cognitoIdentityId == null || "".equals(cognitoIdentityId.trim())) {
+ log.warn("Cognito identity id in request is null");
+ }
+ servletRequest.setAttribute(COGNITO_IDENTITY_ATTRIBUTE, cognitoIdentityId);
+ filterChain.doFilter(servletRequest, servletResponse);
+ }
+
+
+ @Override
+ public void destroy() {
+ // nothing to do in destroy
+ }
+}
diff --git a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Owner.java b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Owner.java
new file mode 100644
index 000000000..f048e6906
--- /dev/null
+++ b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Owner.java
@@ -0,0 +1,20 @@
+package com.amazonaws.serverless.sample.springboot3.model;
+
+import java.util.Arrays;
+import java.util.List;
+
+public record Owner (String id, String firstName, String lastName) {
+
+ private static List owners = Arrays.asList(
+ new Owner("owner-1", "Joshua", "Bloch"),
+ new Owner("owner-2", "Douglas", "Adams"),
+ new Owner("owner-3", "Bill", "Bryson")
+ );
+
+ public static Owner getById(String id) {
+ return owners.stream()
+ .filter(owner -> owner.id().equals(id))
+ .findFirst()
+ .orElse(null);
+ }
+}
diff --git a/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Pet.java b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Pet.java
new file mode 100644
index 000000000..f97b973d0
--- /dev/null
+++ b/samples/springboot3/graphql-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/model/Pet.java
@@ -0,0 +1,20 @@
+package com.amazonaws.serverless.sample.springboot3.model;
+
+import java.util.Arrays;
+import java.util.List;
+
+public record Pet (String id, String name, String breed, String ownerId) {
+
+ private static List pets = Arrays.asList(
+ new Pet("pet-1", "Alpha", "Bulldog", "owner-1"),
+ new Pet("pet-2", "Max", "German Shepherd", "owner-2"),
+ new Pet("pet-3", "Rockie", "Golden Retriever", "owner-3")
+ );
+
+ public static Pet getById(String id) {
+ return pets.stream()
+ .filter(pet -> pet.id().equals(id))
+ .findFirst()
+ .orElse(null);
+ }
+}
diff --git a/samples/springboot3/graphql-pet-store/src/main/resources/graphql/schema.graphqls b/samples/springboot3/graphql-pet-store/src/main/resources/graphql/schema.graphqls
new file mode 100644
index 000000000..293cdcc40
--- /dev/null
+++ b/samples/springboot3/graphql-pet-store/src/main/resources/graphql/schema.graphqls
@@ -0,0 +1,16 @@
+type Query {
+ petById(id: ID): Pet
+}
+
+type Pet {
+ id: ID
+ name: String
+ breed: String
+ owner: Owner
+}
+
+type Owner {
+ id: ID
+ firstName: String
+ lastName: String
+}
diff --git a/samples/springboot3/graphql-pet-store/src/main/resources/logback.xml b/samples/springboot3/graphql-pet-store/src/main/resources/logback.xml
new file mode 100644
index 000000000..8ff988992
--- /dev/null
+++ b/samples/springboot3/graphql-pet-store/src/main/resources/logback.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/samples/springboot3/graphql-pet-store/template.yml b/samples/springboot3/graphql-pet-store/template.yml
new file mode 100644
index 000000000..ce5dcc6b1
--- /dev/null
+++ b/samples/springboot3/graphql-pet-store/template.yml
@@ -0,0 +1,32 @@
+AWSTemplateFormatVersion: '2010-09-09'
+Transform: AWS::Serverless-2016-10-31
+Description: Example Pet Store API written with SpringBoot3, Spring for GraphQl and the aws-serverless-java-container library
+
+Globals:
+ Api:
+ # API Gateway regional endpoints
+ EndpointConfiguration: REGIONAL
+
+Resources:
+ PetStoreFunction:
+ Type: AWS::Serverless::Function
+ Properties:
+ Handler: com.amazonaws.serverless.sample.springboot3.StreamLambdaHandler::handleRequest
+ Runtime: java21
+ CodeUri: .
+ MemorySize: 1024
+ Policies: AWSLambdaBasicExecutionRole
+ Timeout: 60
+ Events:
+ HttpApiEvent:
+ Type: HttpApi
+ Properties:
+ TimeoutInMillis: 20000
+ PayloadFormatVersion: '1.0'
+
+Outputs:
+ SpringBootPetStoreApi:
+ Description: URL for application
+ Value: !Sub 'https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com/graphql'
+ Export:
+ Name: SpringBootPetStoreApi