-
Notifications
You must be signed in to change notification settings - Fork 566
Added SpringBoot3-GraphQL sample #751
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Serverless Spring Boot 3 and Spring-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" | ||
|
||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>com.amazonaws.serverless.sample</groupId> | ||
<artifactId>serverless-springboot3-example</artifactId> | ||
<version>2.0-SNAPSHOT</version> | ||
<name>Spring Boot example for the aws-serverless-java-container library</name> | ||
<description>Simple pet store written with the Spring framework and Spring Boot</description> | ||
<url>https://aws.amazon.com/lambda/</url> | ||
|
||
<parent> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-parent</artifactId> | ||
<version>3.2.2</version> | ||
</parent> | ||
|
||
<licenses> | ||
<license> | ||
<name>The Apache Software License, Version 2.0</name> | ||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> | ||
<distribution>repo</distribution> | ||
</license> | ||
</licenses> | ||
|
||
<properties> | ||
<java.version>21</java.version> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-graphql</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-web</artifactId> | ||
<exclusions> | ||
<exclusion> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-tomcat</artifactId> | ||
</exclusion> | ||
</exclusions> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.graphql</groupId> | ||
<artifactId>spring-graphql-test</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.amazonaws.serverless</groupId> | ||
<artifactId>aws-serverless-java-container-springboot3</artifactId> | ||
<version>2.0.0-SNAPSHOT</version> | ||
</dependency> | ||
</dependencies> | ||
|
||
<profiles> | ||
<profile> | ||
<id>shaded-jar</id> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-shade-plugin</artifactId> | ||
<version>3.5.1</version> | ||
<configuration> | ||
<createDependencyReducedPom>false</createDependencyReducedPom> | ||
</configuration> | ||
<executions> | ||
<execution> | ||
<phase>package</phase> | ||
<goals> | ||
<goal>shade</goal> | ||
</goals> | ||
<configuration> | ||
<artifactSet> | ||
<excludes> | ||
<exclude>org.apache.tomcat.embed:*</exclude> | ||
</excludes> | ||
</artifactSet> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</profile> | ||
<profile> | ||
<id>assembly-zip</id> | ||
<activation> | ||
<activeByDefault>true</activeByDefault> | ||
</activation> | ||
<build> | ||
<plugins> | ||
<!-- don't build a jar, we'll use the classes dir --> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-jar-plugin</artifactId> | ||
<version>3.3.0</version> | ||
<executions> | ||
<execution> | ||
<id>default-jar</id> | ||
<phase>none</phase> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-install-plugin</artifactId> | ||
<version>3.1.1</version> | ||
<configuration> | ||
<skip>true</skip> | ||
</configuration> | ||
</plugin> | ||
<!-- select and copy only runtime dependencies to a temporary lib folder --> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-dependency-plugin</artifactId> | ||
<version>3.6.1</version> | ||
<executions> | ||
<execution> | ||
<id>copy-dependencies</id> | ||
<phase>package</phase> | ||
<goals> | ||
<goal>copy-dependencies</goal> | ||
</goals> | ||
<configuration> | ||
<outputDirectory>${project.build.directory}/lib</outputDirectory> | ||
<includeScope>runtime</includeScope> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-assembly-plugin</artifactId> | ||
<version>3.6.0</version> | ||
<executions> | ||
<execution> | ||
<id>zip-assembly</id> | ||
<phase>package</phase> | ||
<goals> | ||
<goal>single</goal> | ||
</goals> | ||
<configuration> | ||
<finalName>${project.artifactId}-${project.version}</finalName> | ||
<descriptors> | ||
<descriptor>src${file.separator}assembly${file.separator}bin.xml</descriptor> | ||
</descriptors> | ||
<attach>false</attach> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</profile> | ||
</profiles> | ||
|
||
|
||
</project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd"> | ||
<id>lambda-package</id> | ||
<formats> | ||
<format>zip</format> | ||
</formats> | ||
<includeBaseDirectory>false</includeBaseDirectory> | ||
<fileSets> | ||
<!-- copy runtime dependencies with some exclusions --> | ||
<fileSet> | ||
<directory>${project.build.directory}${file.separator}lib</directory> | ||
<outputDirectory>lib</outputDirectory> | ||
<excludes> | ||
<exclude>tomcat-embed*</exclude> | ||
</excludes> | ||
</fileSet> | ||
<!-- copy all classes --> | ||
<fileSet> | ||
<directory>${project.build.directory}${file.separator}classes</directory> | ||
<includes> | ||
<include>**</include> | ||
</includes> | ||
<outputDirectory>${file.separator}</outputDirectory> | ||
</fileSet> | ||
</fileSets> | ||
</assembly> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
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.boot.web.servlet.support.SpringBootServletInitializer; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Import; | ||
import org.springframework.web.servlet.HandlerAdapter; | ||
import org.springframework.web.servlet.HandlerExceptionResolver; | ||
import org.springframework.web.servlet.HandlerMapping; | ||
import org.springframework.web.servlet.ModelAndView; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like a few of these imports are not used ( Try to check for imports in the other files too (I see There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, Thanks. |
||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; | ||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; | ||
|
||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
|
||
|
||
@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); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<AwsProxyRequest, AwsProxyResponse> 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); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like how the
Spring-graphQl
looks.But I would say either we put
Spring Boot 3 with GraphQL
spring-graphql
(all lower case)Spring Boot 3 and Spring for GraphQL
Spring-GraphQL
if we just want to change casing.(in order of my personal preference)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, makes sense. I went with the first option.