8

I'm trying to integrate Google Guice in AWS Lambda but for some reasons, injection is not working well. It give me null whenever i try to call

Handler Code:

public class FirstLamdba implements RequestHandler<Request, Object>{   

        private UserService userService;

        @Inject
        public void seUserService(UserService userService) {
            this.userService = userService;
        }

        public Object handleRequest(Request request, Context context){

            userService.persistData();
}

UserService

public interface UserService {
    List<String> persistData();
}

UserServiceImpl

public class UserServiceImpl implements UserService{


    @Override
    public List<String> persistData() {

        System.out.println("***Working*********");
}

Binding Class:

public class MessageGuiceModule extends AbstractModule
{
  protected void configure() {

    bind(UserService.class).to(UserServiceImpl.class);
  }
}

Test Class:

 @Test
        public void testLambdaFunctionHandler() {
Request request = new Request();
            request.setName("Name");
            FirstLamdba handler = new FirstLamdba();
            Context ctx = createContext();

            Object output = handler.handleRequest(request, ctx);

            // TODO: validate output here if needed.
            if (output != null) {
                System.out.println(output.toString());
            }
        }

For some reasons, UserService userService is sets as null in FirstLamdba.

Any idea?

user1030128
  • 411
  • 9
  • 23

2 Answers2

6

The first time a lambda function is invoked, the environment will be created.

public class FirstLamdba implements RequestHandler<Request, Object>{   

        Injector injector = Guice.createInjector(new MessageGuiceModule());
        private UserService userService = injector.getInstance(UserService.class);


        //setter for testing purpose
        public void setUserService(UserService userService) {
            this.userService = userService;
        }

        public Object handleRequest(Request request, Context context){

            userService.persistData();
}


@Test
public void testLambdaFunctionHandler() {
        Request request = new Request();
        request.setName("Name");
        FirstLamdba handler = new FirstLamdba();
        handler.setUserService(mockUserService);

        Context ctx = createContext();

        Object output = handler.handleRequest(request, ctx);

        // TODO: validate output here if needed.
        if (output != null) {
            System.out.println(output.toString());
        }
}
frhack
  • 4,862
  • 2
  • 28
  • 25
2

The Lambda RequestHandler instance is not instrumented with Guice, so using @Inject directly inside the RequestHandler class is not going to work. This is why you your userService property is always null.

I haven't tried using Guice with Lambda, but I believe you will have to explicitly call Guice.createInjector() at some point in order to bootstrap Guice dependency injection.

In general when developing AWS Lambda functions I recommend starting with a POJO that does things like bootstrapping your libraries, and exposes a single high-level method like persistUser() that you can easily run and test independently from any Lambda specific code. Once you get that working your Lambda function would simply be a few lines of code that instantiates an instance of this POJO and calls the persistUser() method.

Mark B
  • 183,023
  • 24
  • 297
  • 295
  • thanks Mark.i just gave a try and I'm getting null pointer exception with following code Injector injector = Guice.createInjector(new MessageGuiceModule ()); UserService userService = injector.getInstance(FirstLamdba .class); Am i missing anything? – user1030128 Oct 29 '16 at 20:42
  • That doesn't look like valid code actually. First, which line exactly is giving the NPE? Second, shouldn't you be getting an instance of UserService.class instead of FirstLambda.class? Perhaps edit your question with your updated code so we can see the latest issue clearly. – Mark B Oct 29 '16 at 20:59