Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
Dennis Kieselhorst edited this pageDec 12, 2024 ·23 revisions

AWS Serverless Java Container makes it easy to run your Spring, Spring Boot, Jersey, Struts 2, or Spark applications in AWS Lambda with Amazon API Gateway or an Application Load Balancer. The library defines a set of interfaces and abstract classes required to support other frameworks in the future. Serverless Java Container starts each framework acting as a Servlet container, such as Tomcat, and translates API Gateway proxy events into the request format accepted by the underlying framework, such as anHttpServletRequest orContainerRequest. HTTP responses from the frameworks are translated in the object structure API Gateway expects as a return value from Lambda.

Quick starts

How it works

The primary purpose of the library is to act as a Servlet container; it receives events object from Lambda and translates them to a request object for the framework. Similarly, it translates responses from the framework into valid return values for API Gateway.

Compatibility

The current version of AWS Serverless Java Container (2.x) is compatible with Jakarta EE platform 9 and higher (jakarta.* namespace). For applications using an older version of the Jakarta EE platform (javax.* namespace) it's required to use version1.x of Serverless Java Container library.

Lambda handler classes

The framework can be used with bothPOJO andstream handlers. For applications that leverage context values from custom authorizers, we recommend using a stream handler: The framework uses Jackson's@JsonAnySetter/Getter annotations to extract custom values from the authorizer context, the serializer included in AWS Lambda does not process annotated fields. In all our samples, we use theRequestStreamHandler interface and theproxyStream method of the Serverless Java Container library. With a POJO-based handler, you can use theproxy method of the handler object directly.

This is the basic example of a stream handler using Jersey:

publicclassStreamLambdaHandlerimplementsRequestStreamHandler {privatestaticfinalResourceConfigjerseyApplication =newResourceConfig()                                                             .packages("com.amazonaws.serverless.sample.jersey")                                                             .register(JacksonFeature.class);privatestaticfinalJerseyLambdaContainerHandler<AwsProxyRequest,AwsProxyResponse>handler            =JerseyLambdaContainerHandler.getAwsProxyHandler(jerseyApplication);@OverridepublicvoidhandleRequest(InputStreaminputStream,OutputStreamoutputStream,Contextcontext)throwsIOException {handler.proxyStream(inputStream,outputStream,context);    }}

If you are usingLambda Function URLs orHTTP APIs instead ofRest APIs with Amazon API Gateway and plan to useversion 2.0 of the integration event, you can call thegetHttpApiV2ProxyHandler method to get a pre-configuredContainerHandler object:

privatestaticfinalJerseyLambdaContainerHandler<HttpApiV2ProxyRequest,AwsProxyResponse>handler            =JerseyLambdaContainerHandler.getHttpApiV2ProxyHandler(jerseyApplication);

In the example above, and all other sample applications, the mainLambdaContainerHandler is declared in a static block as a class member. This is because static variables are initialized with the runtime (the JVM) as AWS Lambda launches our function, which gives us better performance.

Thesamples directory in the repository contains a sample pet store application for each framework. All of the samples include a stream handler as well as aSAM template for deployment.

Deploying the sample applications

Thesamples folder includes a simple pet store application implemented with each framework supported by this library. With each application, we have included a Mavenpom.xml file, Gradle build file, and aSAM template.The easiest way to deploy the samples it to use theSAM CLI.

Before proceeding, make sure you haveGradle orMaven installed, theAWS CLI installed and configured with a set of AWS credentials, and theSAM CLI.

  • Using a shell, navigate to the folder for the sample application
$cd~/library-folder/samples/springboot3/pet-store
  • In the root folder of the application, run the build command to compile the code and prepare a deployment package for AWS Lambda
$ sam build
  • Once the build completes, use the guided deployment process in the SAM CLI to deploy the application to your AWS account
$ sam deploy --guided
  • The deploy command outputs the API endpoint you can use to test the sample app. Use a browser orcurl in your shell to test the API
...---------------------------------------------------------------------------------------------------------OutputKey-Description                        OutputValue---------------------------------------------------------------------------------------------------------PetStoreApi - URLfor application            https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/pets---------------------------------------------------------------------------------------------------------$ curl https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/pets

Additional configurations

Asynchronous initialization

Since version 1.4 of the framework, we have added the ability to initialize the frameworks in a background thread to avoid exceeding Lambda's cold start maximum time (10 seconds). As of version 2.0.0 this will be automatically in for on-demand mode (not for provisioned concurrency and SnapStart). To initialize the framework asynchronously for older versions, you can use theHandlerBuilder object with anAsyncInitializationWrapper:

SpringBootLambdaContainerHandler<AwsProxyRequest,AwsProxyResponse>handler =newSpringBootProxyHandlerBuilder<AwsProxyRequest>()                    .defaultProxy()                    .asyncInit()                    .springBootApplication(SlowTestApplication.class)                    .buildAndInitialize();

Starting the handler in this way will cause this library to create a background thread and call the initialize method of the framework in the background thread. If the 10 seconds timeout expires and the framework has not completed its initialization, this library returns control to Lambda and continue waiting inside the handler method when it receives the first event. By default, the library will wait for up to20 seconds for the initialization to complete - 10 seconds of Lambda init time + 10 seconds inside the handler method. You can customize this timeout using theContainerConfig object.

// set the initialization timeout to 29 secondsLambdaContainerHandler.getContainerConfig().setInitializationTimeout(29_000);SpringBootLambdaContainerHandler<AwsProxyRequest,AwsProxyResponse>handler =newSpringBootProxyHandlerBuilder<AwsProxyRequest>()                    .defaultProxy()                    .asyncInit()                    .springBootApplication(SlowTestApplication.class)                    .buildAndInitialize();

Application Load Balancer integration

To use an AWS Lambda function created with serverless-java-container as a target for an Application Load Balancer (ALB), you must first enablemulti-value headers support.

Security and API Gateway context

API Gateway supports authentication and authorization using IAM credentials (SigV4) or bearer tokens viaCognito User Pools orcustom authorizers.

The library contains a default implementation of the SecurityContextWriter that supports API Gateway's proxy integration. The generated security context uses the API Gateway$context object to establish the request security context.

ThePrincipal object is populated for all requests in theSecurityContext and can be retrieved from theServletRequests and Jersey'sContainerRequest or injected in an object.

With Jersey, you can inject theSecurityContext using the@Context annotation.

@Path("/test")@GETpublicStringtestPrincipal(@ContextSecurityContextsecurityContext) {Principalprincipal =securityContext.getUserPrincipal();// the possible values for the authentication scheme are// 1. CUSTOM_AUTHORIZER// 2. COGNITO_USER_POOL// 3. AWS_IAM// These are defined as constants in the AwsProxySecurityContext objectStringauthScheme =securityContext.getAuthenticationScheme();}

For servlet-based implementations such as Spring and Spark, you can retrieve the principal from theHttpServletRequest object using thegetUserPrincipal() method.

@RequestMapping(path ="/test",method=RequestMethod.GET)publicStringtest(HttpServletRequestrequest,ServletResponseresponse) {Principalprincipal =request.getUserPrincipal();return"Hello, " +principal.getName() +"!";}

Behind the scenes, for requests authorized via IAM credentials, all information about the user is available in theApiGatewayRequestContext object and itsidentity property. Custom authorizer data, including any custom values, are stored in theApiGatewayAuthorizerContext object.

Context information that are not part of the standard HTTP request, such as the Cognito identity or custom authorizer claims, are stored in request attributes by theRequestReader object. From your implementations, you can access this data using thegetAttribute(String) method of the request object. The example below extracts the API Gateway context property from the request and reads the "picture" value from the custom authorizer claims.

get("/pets", (req,res) -> {ApiGatewayRequestContextctx = (ApiGatewayRequestContext)req.raw().getAttribute(API_GATEWAY_CONTEXT_PROPERTY);ApiGatewayAuthorizerContextauthCtx =ctx.getAuthorizer();Stringpicture =authCtx.getContextValue("picture");});

Servlet filters

You can registerFilter implementations by implementing aStartupsHandler as defined in theAwsLambdaServletContainerHandler class. TheonStartup methods receives a reference to the currentServletContext.

handler.onStartup(c -> {FilterRegistration.Dynamicregistration =c.addFilter("CustomHeaderFilter",CustomHeaderFilter.class);// update the registration to map to a pathregistration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST),true,"/*");// servlet name mappings are disabled and will throw an exception});

Custom domain names

When using this framework with a custom domain name, you need to explicitly enable the domain name in theContainerConfig object.

LambdaContainerHandler.getContainerConfig().addCustomDomain("api.myserver.com");

Unless the custom domain name is explicitly enabled, thegetServerName() method of theHttpServletRequest object will return the default API Gateway domain.

Request logging

The Serverless Java Container library can log requests to the function's CloudWatch log stream. To format the log for each request, the library relies on implementations of theLogFormatter interface. By default, we include an implementation of the interface that generatesApache combined logs. The object is instantiated automatically by the servlet implementation of the library. You can override the formatter to create your own custom log lines using thesetLogFormatter( ) method of theContainerHandler class of your choice.

Container configuration

The library includes aContainerConfig object. When the handler object is initialized, the config is set to its default values. You can change the configuration by retrieving the singleton config from theLambdaContainerHandler object.

LambdaContainerHandler.getContainerConfig().setUseStageAsServletContext(true);

The configuration variables are:

  • serviceBasePath - The value of this propety tells the library whether the application is running under a base path. For example, you could have configured your API Gateway to have a/orders/{proxy+} and a/catalog/{proxy+} resource. Each resource is handled by a separate Lambda functions. For this reason, the application inside Lambda may not be aware of the fact that the/orders path exists. Use theserviceBasePath property in conjuction with thestripBasePath property to remove the/orders prefix when routing requests inside the application. Defaults tonull.
  • stripBasePath - Tells the library to remove the base path specified in theserviceBasePath property before sending the HTTP request for routing to the underlying framework. Defaults tofalse.
  • uriEncoding - Specifies the charset to use when encoding uri components. Defaults toUTF-8.
  • consolidateCookieHeaders - API Gateway only supports a single header value per key. Some applications could return multipleSet-Cookie header in a response. This property tells the framework to group all of the values for the variousSet-Cookie headers into a singleSet-Cookie header separating them with,. Defaults totrue.
  • useStageAsServletContext - Tells the framework to include the API Gateway stage path in theHttpServletRequest context path property. Defaults tofalse.
  • addValidPath - Adds a supported base path to the container. This can be used for API Gateway custom domain base path mappings.
  • addCustomDomainName - Adds a supported custom domain name. Domain names need to be explicitly enabled for thegetServerName() method to return the correct address.
  • enableLocalhost - Enables localhost as a valid domain name for the API. This option enables local testing with theSAM CLI for APIs that use a custom domain name when deployed to AWS.
  • setQueryStringCaseSensitive - Configures case sensitivity when looking up query string parameter names. Defaults tofalse.
  • addBinaryContentTypes - Configures the given content types to be always treated as binary by the framework.
  • setDefaultContentCharset - Overrides the default charset for requests that do not specify one in theContent-Type header. Defaults toISO-8859-1.
  • setInitializationTimeout - Sets the max time aviable to an application to initialize when using an Asynchronous initialization wrapper in milliseconds. Defaults to20_000.
  • setDisableExceptionMapper - Disables exception mapping and allows exceptions thrown by the application to bubble up to the Lambda handler object. Defaults tofalse.

Event translation

To translate incoming events, the library declares two abstract classes: TheRequestReader and theResponseWriter. Both these classes use generic types for the input and output objects. Implementing libraries, such as theJersey one, extend these classes to support their types.

Out of the box, the library supportsproxy integration events.

Clone this wiki locally

[8]ページ先頭

©2009-2025 Movatter.jp