Search code examples
javalagom

How to access configuration in a Lagom service at startup?


I am migrating my current app in Spring/J2EE to Lagom. I am working in Java. I need to read variables from the configuration (application.conf in resources folder). In the implementation module, I try to inject configuration as a class variable like this

@Inject private Configuration config

but when I access this config object in the constructor, it gives null pointer exception.

The whole code is like this

import play.Configuration;

public class SomeServiceImpl implements SomeService {

    @Inject
    private Configuration config;

    public SomeServiceImpl() {
         //getting configuration from application.conf
         // gives exception as config is null.
        String key = config.getString(“key”);
    }

    @Override
    public ServiceCall<Request, Response> send() {
         //works here, does not give exception
         String key = config.getString(“key”);
    }
 }

Sorry, I should have been clear from the beginning. I have edited the original question. I get null pointer exception when I try to read from configuration object in constructor but I am able to use it in service call implementation. I want some way in which I can access the configuration in application.conf at startup and possibly store in some config class which can be accessed anywhere later.


Solution

  • In Java, when an object is instantiated, the first thing that happens (before anything else can possibly happen) is the constructor is invoked. After that, frameworks like Guice (which Lagom uses) are free to inject things, but they can't do it until the constructor has been invoked. So, all your @Inject annotated fields will be null when the constructor is invoked, there is nothing you can do to work around that.

    So, don't use field injection, use constructor injection, eg:

    import play.Configuration;
    
    public class SomeServiceImpl implements SomeService {
    
      private final Configuration config;
    
      @Inject
      public SomeServiceImpl(Configuration config) {
         this.config = config;
         String key = config.getString("key");
      }
    
      @Override
      public ServiceCall<Request, Response> send() {
        String key = config.getString("key");
      }
    }
    

    Constructor injection is not just recommended for this use case, you should be using it everywhere, it avoids all these potential issues.