tariq zafar
tariq zafar

Reputation: 659

Guice on-demand injection

I have been learning about Guice. I see that there is an on-demand injection here.

I wanted to know what it is used for and some example. I have a scenario where I read a set of properties from a conf file. There is no injection there. Later on I want to inject the same instance of the config class I have from those properties to some other class.

class Props {
    //set of properties read from a config file to this class

}

Props props = readProperties(); // instance of this class having all the properties but not put into injection container

Later in connection class I want to use its injection

@Inject
public Connection(Props props) {
    this.props = props;
}

Is it possible to use on-demand injection of Guice in this case? Also I am using Play framework's conf file to load my module file. play.modules.enabled += com.example.mymodule

Upvotes: 2

Views: 1535

Answers (2)

Lachezar Balev
Lachezar Balev

Reputation: 12021

If you want to use the very same configuration instance (of class Props) you could bind its instance as a singleton with a provider binding. This is of course not the only solution, but it makes sense for me.

Here is an example:

Define a provider:

public class PropsProvider implements Provider<Props>
{
    @Override
    public Props get()
    {
        ...read and return Props here...
    }
}

Use a provider binding in singleton scope:

bind(Props.class).toProvider(PropsProvider.class).in(Singleton.class);

Inject your configuration:

@Inject
public Connection(Props props) {
    this.props = props;
}

You may read in the documentation:

Singletons are most useful for:

  • stateful objects, such as configuration or counters
  • objects that are expensive to construct or lookup
  • objects that tie up resources, such as a database connection pool.

Maybe your configuration object matches the first and the second criteria. I would avoid reading the configuration from within the module. See why here.

I've used on-demand injection in a few unit test cases where I wanted to inject mock dependencies in the component under test and field injection was used (that's why I try to avoid field injections :-) ) AND I preferred not to use InjectMocks for certain reasons.

Here is a sample:

Component:

class SomeComponent
{
    @Inject
    Dependency dep;

    void doWork()
    {
        //use dep here
    }
}

The test itself:

@RunWith(MockitoJUnitRunner.class)
public class SomeComponentTest
{
    @Mock
    private Dependency mockDependency;

    private SomeComponent componentToTest;

    @Before
    public void setUp() throws Exception
    {
        componentToTest = new SomeComponent();

        Injector injector = Guice.createInjector(new AbstractNamingModule()
        {
            @Override
            protected void configure()
            {
                bind(Dependency.class).toInstance(mockDependency);
            }
        });

        injector.injectMembers(componentToTest);
    }

    @Test
    public void test()
    {
         //test the component and/or proper interaction with the dependency
    }

}

Upvotes: 3

Jan Galinski
Jan Galinski

Reputation: 11993

Load the properties in your module and them via bindConstant

Upvotes: 1

Related Questions