Skip to content

Commit

Permalink
First import of changes for #142 - build is broken but working on fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
sapessi committed Apr 6, 2018
1 parent 6cd0ab7 commit 5d82f78
Show file tree
Hide file tree
Showing 12 changed files with 216 additions and 154 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package com.amazonaws.serverless.proxy.internal;


import com.amazonaws.serverless.exceptions.ContainerInitializationException;
import com.amazonaws.serverless.proxy.LogFormatter;
import com.amazonaws.serverless.proxy.internal.servlet.ApacheCombinedServletLogFormatter;
import com.amazonaws.serverless.proxy.model.ContainerConfig;
Expand Down Expand Up @@ -100,6 +101,8 @@ protected LambdaContainerHandler(Class<RequestType> requestClass,
this.responseWriter = responseWriter;
this.securityContextWriter = securityContextWriter;
this.exceptionHandler = exceptionHandler;
objectReader = getObjectMapper().readerFor(requestTypeClass);
objectWriter = getObjectMapper().writerFor(responseTypeClass);
}


Expand All @@ -113,6 +116,8 @@ protected LambdaContainerHandler(Class<RequestType> requestClass,
protected abstract void handleRequest(ContainerRequestType containerRequest, ContainerResponseType containerResponse, Context lambdaContext)
throws Exception;

public abstract void initialize()
throws ContainerInitializationException;

//-------------------------------------------------------------
// Methods - Public
Expand Down Expand Up @@ -191,16 +196,9 @@ public void proxyStream(InputStream input, OutputStream output, Context context)
throws IOException {

try {
if (objectReader == null) {
objectReader = getObjectMapper().readerFor(requestTypeClass);
}
RequestType request = objectReader.readValue(input);
ResponseType resp = proxy(request, context);

if (objectWriter == null) {
objectWriter = getObjectMapper().writerFor(responseTypeClass);
}

objectWriter.writeValue(output, resp);
} catch (JsonParseException e) {
log.error("Error while parsing request object stream", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ public abstract class AwsLambdaServletContainerHandler<RequestType, ResponseType
//-------------------------------------------------------------
// Variables - Private
//-------------------------------------------------------------

protected ServletContext servletContext;
private Logger log = LoggerFactory.getLogger(AwsLambdaServletContainerHandler.class);
private FilterChainManager<AwsServletContext> filterChainManager;
private boolean startupExecuted;

//-------------------------------------------------------------
// Variables - Protected
//-------------------------------------------------------------
protected StartupHandler startupHandler;
private FilterChainManager<AwsServletContext> filterChainManager;
protected ServletContext servletContext;


//-------------------------------------------------------------
Expand All @@ -78,6 +78,8 @@ protected AwsLambdaServletContainerHandler(Class<RequestType> requestTypeClass,
super(requestTypeClass, responseTypeClass, requestReader, responseWriter, securityContextWriter, exceptionHandler);
// set the default log formatter for servlet implementations
setLogFormatter(new ApacheCombinedServletLogFormatter<>());
setServletContext(new AwsServletContext(this));
startupExecuted = false;
}

//-------------------------------------------------------------
Expand Down Expand Up @@ -154,17 +156,7 @@ private HttpServletResponse getServletResponse(ContainerResponseType resp) {
*/
public void onStartup(final StartupHandler h) {
startupHandler = h;
}

@Override
protected void handleRequest(ContainerRequestType containerRequest, ContainerResponseType containerResponse, Context lambdaContext)
throws Exception {
// The servlet context should not be linked to a specific request object, only to the Lambda
// context so we only set it once.
// TODO: In the future, if we decide to support multiple servlets/contexts in an instance we only need to modify this method
if (getServletContext() == null) {
setServletContext(new AwsServletContext(this));
}
startupHandler.onStartup(getServletContext());
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,8 @@ public class JerseyLambdaContainerHandler<RequestType, ResponseType> extends Aws
//-------------------------------------------------------------

private JerseyHandlerFilter jerseyFilter;

// tracker for the first request
private boolean initialized;


//-------------------------------------------------------------
// Methods - Public - Static
//-------------------------------------------------------------
Expand All @@ -98,13 +95,15 @@ public class JerseyLambdaContainerHandler<RequestType, ResponseType> extends Aws
* @return A <code>JerseyLambdaContainerHandler</code> object
*/
public static JerseyLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> getAwsProxyHandler(Application jaxRsApplication) {
return new JerseyLambdaContainerHandler<>(AwsProxyRequest.class,
AwsProxyResponse.class,
new AwsProxyHttpServletRequestReader(),
new AwsProxyHttpServletResponseWriter(),
new AwsProxySecurityContextWriter(),
new AwsProxyExceptionHandler(),
jaxRsApplication);
JerseyLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> newHandler = new JerseyLambdaContainerHandler<>(AwsProxyRequest.class,
AwsProxyResponse.class,
new AwsProxyHttpServletRequestReader(),
new AwsProxyHttpServletResponseWriter(),
new AwsProxySecurityContextWriter(),
new AwsProxyExceptionHandler(),
jaxRsApplication);
newHandler.initialize();
return newHandler;
}


Expand Down Expand Up @@ -133,8 +132,7 @@ public JerseyLambdaContainerHandler(Class<RequestType> requestTypeClass,

super(requestTypeClass, responseTypeClass, requestReader, responseWriter, securityContextWriter, exceptionHandler);
Timer.start("JERSEY_CONTAINER_CONSTRUCTOR");
this.initialized = false;

initialized = false;
if (jaxRsApplication instanceof ResourceConfig) {
((ResourceConfig)jaxRsApplication).register(new AbstractBinder() {
@Override
Expand Down Expand Up @@ -162,29 +160,28 @@ protected AwsHttpServletResponse getContainerResponse(AwsProxyHttpServletRequest
@Override
protected void handleRequest(AwsProxyHttpServletRequest httpServletRequest, AwsHttpServletResponse httpServletResponse, Context lambdaContext)
throws Exception {

Timer.start("JERSEY_HANDLE_REQUEST");
// this method of the AwsLambdaServletContainerHandler sets the request context
super.handleRequest(httpServletRequest, httpServletResponse, lambdaContext);

// we retain the initialized property for backward compatibility
if (!initialized) {
Timer.start("JERSEY_COLD_START_INIT");
// call the onStartup event if set to give developers a chance to set filters in the context
if (startupHandler != null) {
startupHandler.onStartup(getServletContext());
}

// manually add the spark 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), true, "/*");

initialized = true;
Timer.stop("JERSEY_COLD_START_INIT");
initialize();
}
Timer.start("JERSEY_HANDLE_REQUEST");

httpServletRequest.setServletContext(getServletContext());

doFilter(httpServletRequest, httpServletResponse, null);
Timer.stop("JERSEY_HANDLE_REQUEST");
}


@Override
public void initialize() {
Timer.start("JERSEY_COLD_START_INIT");

// manually add the spark 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), true, "/*");

Timer.stop("JERSEY_COLD_START_INIT");
initialized = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,18 @@ public class SparkLambdaContainerHandler<RequestType, ResponseType>
*/
public static SparkLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> getAwsProxyHandler()
throws ContainerInitializationException {
return new SparkLambdaContainerHandler<>(AwsProxyRequest.class,
AwsProxyResponse.class,
new AwsProxyHttpServletRequestReader(),
new AwsProxyHttpServletResponseWriter(),
new AwsProxySecurityContextWriter(),
new AwsProxyExceptionHandler(),
new LambdaEmbeddedServerFactory());
SparkLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> 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;
}

//-------------------------------------------------------------
Expand Down Expand Up @@ -180,36 +185,36 @@ protected AwsHttpServletResponse getContainerResponse(AwsProxyHttpServletRequest
protected void handleRequest(AwsProxyHttpServletRequest httpServletRequest, AwsHttpServletResponse httpServletResponse, Context lambdaContext)
throws Exception {
Timer.start("SPARK_HANDLE_REQUEST");
// this method of the AwsLambdaServletContainerHandler sets the request context
super.handleRequest(httpServletRequest, httpServletResponse, lambdaContext);

if (embeddedServer == null) {
Timer.start("SPARK_COLD_START");
log.debug("First request, getting new server instance");
initialize();
}

// trying to call init in case the embedded server had not been initialized.
Spark.init();
httpServletRequest.setServletContext(getServletContext());

// adding this call to make sure that the framework is fully initialized. This should address a race
// condition and solve GitHub issue #71.
Spark.awaitInitialization();
doFilter(httpServletRequest, httpServletResponse, null);
Timer.stop("SPARK_HANDLE_REQUEST");
}

embeddedServer = lambdaServerFactory.getServerInstance();

// call the onStartup event if set to give developers a chance to set filters in the context
if (startupHandler != null) {
startupHandler.onStartup(getServletContext());
}
@Override
public void initialize()
throws ContainerInitializationException {
Timer.start("SPARK_COLD_START");
log.debug("First request, getting new server instance");

// manually add the spark filter to the chain. This should the last one and match all uris
FilterRegistration.Dynamic sparkRegistration = getServletContext().addFilter("SparkFilter", embeddedServer.getSparkFilter());
sparkRegistration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
Timer.stop("SPARK_COLD_START");
}
// trying to call init in case the embedded server had not been initialized.
Spark.init();

httpServletRequest.setServletContext(getServletContext());
// adding this call to make sure that the framework is fully initialized. This should address a race
// condition and solve GitHub issue #71.
Spark.awaitInitialization();

doFilter(httpServletRequest, httpServletResponse, null);
Timer.stop("SPARK_HANDLE_REQUEST");
embeddedServer = lambdaServerFactory.getServerInstance();

// manually add the spark filter to the chain. This should the last one and match all uris
FilterRegistration.Dynamic sparkRegistration = getServletContext().addFilter("SparkFilter", embeddedServer.getSparkFilter());
sparkRegistration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
Timer.stop("SPARK_COLD_START");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.ContextStoppedEvent;
import org.springframework.context.event.GenericApplicationListenerAdapter;
import org.springframework.context.support.AbstractRefreshableApplicationContext;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.ContextLoaderListener;
Expand Down Expand Up @@ -125,6 +127,13 @@ public List<String> getSpringProfiles() {

public void setSpringProfiles(List<String> springProfiles) {
this.springProfiles = new ArrayList<>(springProfiles);
applicationContext.stop();
applicationContext.close();
applicationContext.getEnvironment().setActiveProfiles(springProfiles.toArray(new String[0]));
//applicationContext.start();
applicationContext.refresh();

//dispatcherServlet.refresh();
}

@Override
Expand All @@ -135,20 +144,18 @@ public void onStartup(ServletContext servletContext) throws ServletException {
}
applicationContext.setServletContext(servletContext);


DefaultDispatcherConfig dispatcherConfig = new DefaultDispatcherConfig(servletContext);
applicationContext.setServletConfig(dispatcherConfig);

// Configure the listener for the request handled events. All we do here is release the latch
applicationContext.addApplicationListener(new ApplicationListener<ServletRequestHandledEvent>() {
@Override
public void onApplicationEvent(ServletRequestHandledEvent servletRequestHandledEvent) {
try {
applicationContext.addApplicationListener((ApplicationListener<ServletRequestHandledEvent>) servletRequestHandledEvent -> {
try {
if (currentResponse != null) {
currentResponse.flushBuffer();
} catch (IOException e) {
log.error("Could not flush response buffer", e);
throw new RuntimeException("Could not flush response buffer", e);
}
} catch (IOException e) {
log.error("Could not flush response buffer", e);
throw new RuntimeException("Could not flush response buffer", e);
}
});

Expand Down
Loading

0 comments on commit 5d82f78

Please sign in to comment.