Play java 2.5 guice eager loading and stop hook not working

1k Views Asked by At

This code is in app/ folder :

 public class GuiceConfiguration extends AbstractModule {

        @Override
        protected void configure() {
            bind(KafkaConnection.class).asEagerSingleton();
        }
    }


@Singleton
public class KafkaConnection {

    public KafkaConnection(){
        try {
            ServiceUtils.startKafka();
        } catch (IOException e) {
            PlayLoggerUtils.logError("[Global]", this.getClass(), e);
        }

    }

    public KafkaConnection(ApplicationLifecycle lifecycle) {
        lifecycle.addStopHook(() -> {
            PlayLoggerUtils.logDebug("Kafka shutting down", this.getClass());
            ServiceUtils.shutDownKafka();
            return CompletableFuture.completedFuture(null);
        });

    }


}

In application conf

play.module.enabled += "GuiceConfiguration"

The class is being initialized only if I call inject in controller. It is not loading at time of application startup. And the stop hook is also not being executed (tried with ctrl+d and just kill without force in production mode).

1

There are 1 best solutions below

1
Hugo On

First of all, your class should have only one constructor. If an instance is created with the default constructor, it will definitely not have registered to the application lifecycle.

Further, it is good practice to provide an interface with an implementation. KafkaConnection should be an interface which could have multiple implementations (allows you to stub things when necessary).

With respect to the instance not being loaded eagerly, you use .asEagerSingleton() in your module, as well as the @Singleton annotation. According to the Guice docs:

                      PRODUCTION    DEVELOPMENT
.asEagerSingleton()   eager         eager
.in(Singleton.class)  eager         lazy
.in(Scopes.SINGLETON) eager         lazy
@Singleton            eager         lazy

@Singleton should be loaded lazily in Development mode. Although in production mode, it should be loaded eagerly.

So a working implementation (also on your dev environment) could look something like this:

public class GuiceConfiguration extends AbstractModule {

    @Override
    protected void configure() {
        bind(KafkaConnection.class).to(DefaultKafkaConnection.class).asEagerSingleton();
    }
}

public interface KafkaConnection {}

// No annotation
public class DefaultKafkaConnection implements KafkaConnection {

    // No default constructor, but the ApplicationLifecycle needs
    // to be injected
    @Inject
    public KafkaConnection(ApplicationLifecycle lifecycle) {
        try {
            ServiceUtils.startKafka();
        } catch (IOException e) {
            PlayLoggerUtils.logError("[Global]", this.getClass(), e);
        }
        lifecycle.addStopHook(() -> {
            PlayLoggerUtils.logDebug("Kafka shutting down", this.getClass());
            ServiceUtils.shutDownKafka();
            return CompletableFuture.completedFuture(null);
        });

    }

}