Binding one Instance to Two Interfaces in Guice

15. June, 2018

Sometimes, you need to bind one instance to two interfaces in Guice, for example:

interface Foo { ... }

interface Bar extends Foo { ... }

class FooBarImpl implements Bar { ... }

Let’s imaging FooBarImpl is a stateful bean which is saved in a session scope:

bind(Bar.class)
    .to(FooBarImpl.class)
    .in(Session.class);

This works when someone injects Bar but injecting Foo fails. There are two solutions for this: Bind Foo to Bar or use a provider method to transform the type.

Solution 1: Binding Interfaces

bind(Foo.class)
    .to(Bar.class);

This will use the mapping for Bar to satisfy requests for Foo.

Solution 2: Provider Method

Provider methods are a nice way to build complex objects from bound instances. In our case, we can map the types like so:

@Provides
@Session
public Foo fooProvider(Bar impl) {
    return impl;
}

Note: These approaches will put two keys into your scope but they will point to the same instance.


Cycles in dependency injection

9. November, 2010

There is an old argument in DI: How to handle dependency cycles?

Say you have logging and reading of configuration files. Logging needs the config (how should I log?) and the config needs to log (where was the config read from?). How do you solve that?

It gets worse when people insist that DI fields have to be final (i.e. immutable) or that dependencies must be injected via constructors. How on earth can you create the logger if it needs a config instance as constructor parameter and the config instance needs a logger in the constructor?

The “solution”: Proxies. You create the config instance with a proxy to the real logger, then create the logger with the config instance and finally, you replace the proxy with the logger.

Why is that solution bad?

Because your code now has two bugs: You have a cyclic dependency (bad but sometimes necessary) and you’re trying hard to pretend you don’t have one. If someone will have to fix a bug in there, they won’t expect that the “final” instances can actually change.

On top of that, it makes your code inflexible. My gut feeling is that there is a reason why you can’t add plug-ins to Eclipse without having to restart the whole IDE. The infrastructure to manage plug-ins can add and remove them at runtime – unless you prevent that by using “solutions” code like the one outlined above.

Or as Yoda would have said: Much fear in you I sense.

Get over your fear. Write better unit tests (which will also become more simple if you don’t use final fields). Avoid “final” unless Java forces you to use it.