com.amazonaws.serverless.proxy.jersey.JerseyLambdaContainerHandler 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-jersey Show documentation
Show all versions of aws-serverless-java-container-jersey Show documentation
Allows Java applications written for Jersey to run in AWS Lambda
The newest version!
/*
* 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.jersey;
import com.amazonaws.serverless.proxy.*;
import com.amazonaws.serverless.proxy.internal.servlet.*;
import com.amazonaws.serverless.proxy.internal.testutils.Timer;
import com.amazonaws.serverless.proxy.jersey.suppliers.AwsProxyServletContextSupplier;
import com.amazonaws.serverless.proxy.jersey.suppliers.AwsProxyServletRequestSupplier;
import com.amazonaws.serverless.proxy.jersey.suppliers.AwsProxyServletResponseSupplier;
import com.amazonaws.serverless.proxy.model.AwsProxyRequest;
import com.amazonaws.serverless.proxy.model.AwsProxyResponse;
import com.amazonaws.serverless.proxy.model.HttpApiV2ProxyRequest;
import com.amazonaws.services.lambda.runtime.Context;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.internal.inject.InjectionManager;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.glassfish.jersey.server.ResourceConfig;
import jakarta.servlet.DispatcherType;
import jakarta.servlet.FilterRegistration;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.ws.rs.core.Application;
import java.util.EnumSet;
import java.util.concurrent.CountDownLatch;
/**
* Jersey-specific implementation of the LambdaContainerHandler
interface. Given a Jax-Rs application
* starts Jersey's ApplicationHandler
and proxies requests and responses using the RequestReader and
* ResponseWriter objects. The reader and writer objects are inherited from the BaseLambdaContainerHandler
* object.
*
*
* {@code
* public class LambdaHandler implements RequestHandler {
* private ResourceConfig jerseyApplication = new ResourceConfig().packages("your.app.package");
* private JerseyLambdaContainerHandler container = JerseyLambdaContainerHandler.getAwsProxyHandler(jerseyApplication);
*
* public AwsProxyResponse handleRequest(AwsProxyRequest awsProxyRequest, Context context) {
* return container.proxy(awsProxyRequest, context);
* }
* }
* }
*
*
* @see com.amazonaws.serverless.proxy.internal.LambdaContainerHandler
*
* @param The type for the incoming Lambda event
* @param The type for Lambda's return value
*/
public class JerseyLambdaContainerHandler extends AwsLambdaServletContainerHandler {
//-------------------------------------------------------------
// Variables - Private
//-------------------------------------------------------------
private JerseyHandlerFilter jerseyFilter;
private boolean initialized;
//-------------------------------------------------------------
// Methods - Public - Static
//-------------------------------------------------------------
/**
* Returns an initialized JerseyLambdaContainerHandler
that includes RequestReader
and
* ResponseWriter
objects for the AwsProxyRequest
and AwsProxyResponse
* objects.
*
* @param jaxRsApplication A configured Jax-Rs application object. For Jersey apps this can be the default
* ResourceConfig
object
* @return A JerseyLambdaContainerHandler
object
*/
public static JerseyLambdaContainerHandler getAwsProxyHandler(Application jaxRsApplication) {
JerseyLambdaContainerHandler newHandler = new JerseyLambdaContainerHandler<>(
AwsProxyRequest.class,
AwsProxyResponse.class,
new AwsProxyHttpServletRequestReader(),
new AwsProxyHttpServletResponseWriter(),
new AwsProxySecurityContextWriter(),
new AwsProxyExceptionHandler(),
jaxRsApplication);
newHandler.initialize();
return newHandler;
}
/**
* Returns an initialized JerseyLambdaContainerHandler
that includes RequestReader
and
* ResponseWriter
objects for the HttpApiV2ProxyRequest
and AwsProxyResponse
* objects.
*
* @param jaxRsApplication A configured Jax-Rs application object. For Jersey apps this can be the default
* ResourceConfig
object
* @return A JerseyLambdaContainerHandler
object
*/
public static JerseyLambdaContainerHandler getHttpApiV2ProxyHandler(Application jaxRsApplication) {
JerseyLambdaContainerHandler newHandler = new JerseyLambdaContainerHandler<>(
HttpApiV2ProxyRequest.class,
AwsProxyResponse.class,
new AwsHttpApiV2HttpServletRequestReader(),
new AwsProxyHttpServletResponseWriter(true),
new AwsHttpApiV2SecurityContextWriter(),
new AwsProxyExceptionHandler(),
jaxRsApplication);
newHandler.initialize();
return newHandler;
}
//-------------------------------------------------------------
// Constructors
//-------------------------------------------------------------
/**
* Private constructor for a LambdaContainer. Sets the application object, sets the ApplicationHandler,
* and initializes the application using the onStartup
method.
* @param requestTypeClass The class for the expected event type
* @param responseTypeClass The class for the output type
* @param requestReader A request reader instance
* @param responseWriter A response writer instance
* @param securityContextWriter A security context writer object
* @param exceptionHandler An exception handler
* @param jaxRsApplication The JaxRs application
*/
public JerseyLambdaContainerHandler(Class requestTypeClass,
Class responseTypeClass,
RequestReader requestReader,
ResponseWriter responseWriter,
SecurityContextWriter securityContextWriter,
ExceptionHandler exceptionHandler,
Application jaxRsApplication) {
super(requestTypeClass, responseTypeClass, requestReader, responseWriter, securityContextWriter, exceptionHandler);
Timer.start("JERSEY_CONTAINER_CONSTRUCTOR");
initialized = false;
if (jaxRsApplication instanceof ResourceConfig) {
((ResourceConfig)jaxRsApplication).register(new AbstractBinder() {
@Override
protected void configure() {
bindFactory(AwsProxyServletContextSupplier.class)
.proxy(true)
.proxyForSameScope(true)
.to(ServletContext.class)
.in(RequestScoped.class);
bindFactory(AwsProxyServletRequestSupplier.class)
.proxy(true)
.proxyForSameScope(true)
.to(HttpServletRequest.class)
.in(RequestScoped.class);
bindFactory(AwsProxyServletResponseSupplier.class)
.proxy(true)
.proxyForSameScope(true)
.to(HttpServletResponse.class)
.in(RequestScoped.class);
}
});
}
this.jerseyFilter = new JerseyHandlerFilter(jaxRsApplication);
Timer.stop("JERSEY_CONTAINER_CONSTRUCTOR");
}
//-------------------------------------------------------------
// Methods - Implementation
//-------------------------------------------------------------
@Override
protected void handleRequest(HttpServletRequest httpServletRequest, AwsHttpServletResponse httpServletResponse, Context lambdaContext)
throws Exception {
// we retain the initialized property for backward compatibility
if (!initialized) {
initialize();
}
Timer.start("JERSEY_HANDLE_REQUEST");
if (AwsHttpServletRequest.class.isAssignableFrom(httpServletRequest.getClass())) {
((AwsHttpServletRequest)httpServletRequest).setServletContext(getServletContext());
}
doFilter(httpServletRequest, httpServletResponse, null);
Timer.stop("JERSEY_HANDLE_REQUEST");
}
@Override
protected AwsHttpServletResponse getContainerResponse(HttpServletRequest request, CountDownLatch latch) {
return new AwsHttpServletResponse(request, latch);
}
@Override
public void initialize() {
Timer.start("JERSEY_COLD_START_INIT");
// manually add the filter to the chain. This should the last one and match all uris
FilterRegistration.Dynamic jerseyFilterReg = getServletContext().addFilter("JerseyFilter", jerseyFilter);
jerseyFilterReg.addMappingForUrlPatterns(
EnumSet.of(DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.INCLUDE, DispatcherType.FORWARD),
true, "/*"
);
Timer.stop("JERSEY_COLD_START_INIT");
initialized = true;
}
public InjectionManager getInjectionManager() {
if (!initialized) {
initialize();
}
return jerseyFilter.getApplicationHandler().getInjectionManager();
}
public Servlet getServlet() {
return null;
}
}