com.amazonaws.serverless.proxy.spark.SparkLambdaContainerHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aws-serverless-java-container-spark Show documentation
Show all versions of aws-serverless-java-container-spark Show documentation
Allows Java applications written for Spark to run in AWS Lambda
/*
* Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
* with the License. A copy of the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
* OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
package com.amazonaws.serverless.proxy.spark;
import com.amazonaws.serverless.exceptions.ContainerInitializationException;
import com.amazonaws.serverless.proxy.AwsProxyExceptionHandler;
import com.amazonaws.serverless.proxy.AwsProxySecurityContextWriter;
import com.amazonaws.serverless.proxy.ExceptionHandler;
import com.amazonaws.serverless.proxy.RequestReader;
import com.amazonaws.serverless.proxy.ResponseWriter;
import com.amazonaws.serverless.proxy.SecurityContextWriter;
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.internal.servlet.*;
import com.amazonaws.serverless.proxy.spark.embeddedserver.LambdaEmbeddedServer;
import com.amazonaws.serverless.proxy.spark.embeddedserver.LambdaEmbeddedServerFactory;
import com.amazonaws.services.lambda.runtime.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import spark.Service;
import spark.Spark;
import spark.embeddedserver.EmbeddedServers;
import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.EnumSet;
import java.util.concurrent.CountDownLatch;
/**
* Implementation of the LambdaContainerHandler
object that supports the Spark framework: http://sparkjava.com/
*
* Because of the way this container is implemented, using reflection to change accessibility of methods in the Spark
* framework and inserting itself as the default embedded container, it is important that you initialize the Handler
* before declaring your spark routes.
*
* This implementation uses the default AwsProxyHttpServletRequest
and Response implementations.
*
*
* {@code
* // always initialize the handler first
* SparkLambdaContainerHandler handler =
* SparkLambdaContainerHandler.getAwsProxyHandler();
*
* get("/hello", (req, res) -> {
* res.status(200);
* res.body("Hello World");
* });
* }
*
*
* @param The request object used by the RequestReader
implementation passed to the constructor
* @param The response object produced by the ResponseWriter
implementation in the constructor
*/
public class SparkLambdaContainerHandler
extends AwsLambdaServletContainerHandler {
//-------------------------------------------------------------
// Constants
//-------------------------------------------------------------
private static final String LAMBDA_EMBEDDED_SERVER_CODE = "AWS_LAMBDA";
//-------------------------------------------------------------
// Variables - Private
//-------------------------------------------------------------
private LambdaEmbeddedServer embeddedServer;
private LambdaEmbeddedServerFactory lambdaServerFactory;
private Logger log = LoggerFactory.getLogger(SparkLambdaContainerHandler.class);
//-------------------------------------------------------------
// Methods - Public - Static
//-------------------------------------------------------------
/**
* Returns a new instance of an SparkLambdaContainerHandler initialized to work with AwsProxyRequest
* and AwsProxyResponse
objects.
*
* @return a new instance of SparkLambdaContainerHandler
*
* @throws ContainerInitializationException Throws this exception if we fail to initialize the Spark container.
* This could be caused by the introspection used to insert the library as the default embedded container
*/
public static SparkLambdaContainerHandler getAwsProxyHandler()
throws ContainerInitializationException {
SparkLambdaContainerHandler newHandler = new SparkLambdaContainerHandler<>(AwsProxyRequest.class,
AwsProxyResponse.class,
new AwsProxyHttpServletRequestReader(),
new AwsProxyHttpServletResponseWriter(),
new AwsProxySecurityContextWriter(),
new AwsProxyExceptionHandler(),
new LambdaEmbeddedServerFactory());
// For Spark we cannot call intialize here. It needs to be called manually after the routes are set
//newHandler.initialize();
return newHandler;
}
//-------------------------------------------------------------
// Constructors
//-------------------------------------------------------------
public SparkLambdaContainerHandler(Class requestTypeClass,
Class responseTypeClass,
RequestReader requestReader,
ResponseWriter responseWriter,
SecurityContextWriter securityContextWriter,
ExceptionHandler exceptionHandler,
LambdaEmbeddedServerFactory embeddedServerFactory)
throws ContainerInitializationException {
super(requestTypeClass, responseTypeClass, requestReader, responseWriter, securityContextWriter, exceptionHandler);
Timer.start("SPARK_CONTAINER_HANDLER_CONSTRUCTOR");
EmbeddedServers.add(LAMBDA_EMBEDDED_SERVER_CODE, embeddedServerFactory);
this.lambdaServerFactory = embeddedServerFactory;
// TODO: This is pretty bad but we are not given access to the embeddedServerIdentifier property of the
// Service object
try {
AccessController.doPrivileged((PrivilegedExceptionAction