user3301010
user3301010

Reputation: 11

how to do eager singleton initialization in Guice

How to do eager singleton initialization in Guice. I have done in spring in the following way:

<!-- Scheduler to run the artifact metadata refresher. -->
    <bean id="springTest" class="org.springframework.beans.factory.config.MethodInvokingBean"
          scope="singleton">
        <property name="targetObject"  ref="initializer"/>
        <property name="targetMethod" value="createScheduler" />
        <property name="arguments">
            <list>

               .... define arguments

            /***final Runnable artifactRefresherTask,
            final long fixedInitialDelayInSecs,
            final int maxRandomScheduledDelayInSecs,
            final long schedulePeriodInSecs,
            final long awaitTerminationInSecs
           **/

            </list>
        </property>
    </bean>

But in Guice:

if I do this :

   @Singleton
    @Inject
    public void  provideArtifactRefresherScheduler(
            final Runnable artifactRefresherTask,
            final long fixedInitialDelayInSecs,
            final int maxRandomScheduledDelayInSecs,
            final long schedulePeriodInSecs,
            final long awaitTerminationInSecs
            ) {
        new StaggeredScheduler(
                test" /* name of the scheduler.*/,
                StaggeredScheduler.ScheduleStrategy.FIXED_RATE /* scheduler strategy to be used */,
                fixedInitialDelayInSecs,
                maxRandomScheduledDelayInSecs,
                schedulePeriodInSecs,
                artifactRefresherTask,
                true,
                awaitTerminationInSecs);

    }

This does not work. In Guice, I want my StaggeredScheduler to be instantiated as soon as the service starts. Note: StaggeredScheduler constructor initiates the start of the scheduler( that code is not in my control)

Please suggest.

Upvotes: 0

Views: 4079

Answers (1)

Matthew Pope
Matthew Pope

Reputation: 7669

In the configure() method of your Guice module, bind the class as an eager singleton.

protected void configure() {
    bind(StaggeredScheduler.class).toProvider(StaggeredSchedulerProvider.class).asEagerSingleton();
}

And implement Provider<StaggeredScheduler>. For example:

public class StaggeredSchedulerProvider implements Provider<StaggeredScheduler> {

    @Inject
    public StaggeredSchedulerProvider(final Runnable artifactRefresherTask,
                                      final long fixedInitialDelayInSecs,
                                      final int maxRandomScheduledDelayInSecs,
                                      final long schedulePeriodInSecs,
                                      final long awaitTerminationInSecs) {
        this.fixedInitialDelayInSecs = fixedInitialDelayInSecs;
        this.maxRandomScheduledDelayInSecs = maxRandomScheduledDelayInSecs;
        this.schedulePeriodInSecs = schedulePeriodInSecs;
        this.artifactRefresherTask = artifactRefresherTask;
        this.awaitTerminationInSecs = awaitTerminationInSecs;
    }

    public StaggeredScheduler get() {
        new StaggeredScheduler(
            "test", /* name of the scheduler.*/
            StaggeredScheduler.ScheduleStrategy.FIXED_RATE, /* scheduler strategy to be used */
            fixedInitialDelayInSecs,
            maxRandomScheduledDelayInSecs,
            schedulePeriodInSecs,
            artifactRefresherTask,
            true,
            awaitTerminationInSecs);
    }
}

A more quick and dirty hack is to add this to your Guice Module:

@BindingAnnotation
@Retention(RUNTIME)
private @interface PrivateBindingAnnotation {}

protected void configure() {
    bind(StaggeredScheduler.class).annotatedWith(PrivateBindingAnnotation.class).to(StaggeredScheduler.class).asEagerSingleton();
}

@Provides
@Singleton
public StaggeredScheduler provideArtifactRefresherScheduler(
        final Runnable artifactRefresherTask,
        final long fixedInitialDelayInSecs,
        final int maxRandomScheduledDelayInSecs,
        final long schedulePeriodInSecs,
        final long awaitTerminationInSecs) {
    new StaggeredScheduler(
            test" /* name of the scheduler.*/,
            StaggeredScheduler.ScheduleStrategy.FIXED_RATE /* scheduler strategy to be used */,
            fixedInitialDelayInSecs,
            maxRandomScheduledDelayInSecs,
            schedulePeriodInSecs,
            artifactRefresherTask,
            true,
            awaitTerminationInSecs);

}

In either case, you will need to make sure that you are actually able to inject the required values into the Provider or the @Provides method.

Upvotes: 2

Related Questions