4

I'm using aws-serverless-java-container to wrap a Jersey service in a AWS Lambda. I decided to use function alias to have a "test" and "prod" stage that eventually points to different versions of the lambda function.

I need to select some properties in a .properties file based on that alias, basically because I need to talk to a "test" or "prod" DB or use a different endpoint to invoke an external web service.

For such purpose I need to invoke the method getInvokedFunctionArn of the Context object. Unfortunately the Jersey resource is not aware of such context by default.

Below a sample resource:

@Path("/pet")
public class PetResource {

    @POST
    @Path("/")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.WILDCARD)
    public Response createPet() {
        // how to call getInvokedFunctionArn from Lambda context object?
        return Response.status(200).entity("{'result': 'success'}").build();
    }
}

How can I enable the Jersey resource to have the invoked ARN? Can I inject it?

The lambda handler is defined as:

public class PetLambdaHandler implements RequestStreamHandler {

    private static final ResourceConfig jerseyApplication = new ResourceConfig().register(PetResource.class)
            .register(JacksonFeature.class);

    private static final JerseyLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler = JerseyLambdaContainerHandler
            .getAwsProxyHandler(jerseyApplication);

    @Override
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
        handler.proxyStream(inputStream, outputStream, context);
    }
}
Ori Marko
  • 56,308
  • 23
  • 131
  • 233
alessmar
  • 4,689
  • 7
  • 43
  • 52
  • Did my answer helped? if not framework you use/consider for dependency-injection? did you checked https://stackoverflow.com/questions/16216759/dependency-injection-with-jersey-2-0 – Ori Marko Jun 26 '19 at 09:57
  • No, it didn't help. I'm not looking for another DI framework like spring and your solution doesn't outline a way to choose one of the two profiles based on the lambda's execution context. – alessmar Jul 04 '19 at 09:39

2 Answers2

1

You cannot inject the Lambda context automatically. However, you can retrieve it form the ContainerRequestContext object. The serverless-java-container framework adds it as a request property.

You can probably do something like this (have not tested the code):

@GET
public String testLambdaContext(@Context ContainerRequestContext containerRequest) {
   Context lambdaContext =
       (Context) containerRequest.getProperty(RequestReader.LAMBDA_CONTEXT_PROPERTY);
   return lambdaContext.getInvokedFunctionArn()
}
Stefano Buliani
  • 974
  • 7
  • 8
0

You can Inject context to jersey resources using Spring profile

Define for test and prod profiles different methods/objects

If you don't have Spring, you can check jersey integration

jersey-spring4 module that will act as the integration bridge for Spring and Jersey.

See full example in github aws-serverless-java-container library running a Spring application with profiles in AWS Lambda

There are two ways to activate Spring Profiles (as defined with the @Profile annotation). We recommend using the static initializer that receives a list of profiles. The Serverless Java Container framework takes care of setting the profile and initializing the application at once.

public class StreamLambdaHandler implements RequestStreamHandler {
    private static SpringLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
    static {
        try {
            AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
            applicationContext.register(PetStoreSpringAppConfig.class);
            handler = SpringLambdaContainerHandler.getAwsProxyHandler(applicationContext, "profile-1", "profile-2");
Ori Marko
  • 56,308
  • 23
  • 131
  • 233
  • I would prefer to not use another DI framework like Spring, since Jersey already use HK2. Moreover your proposed solution doesn't allow to choose "profile-1" or "profile-2" based on the lambda's execution context. – alessmar Jul 04 '19 at 09:36