Skip to content

Instantly share code, notes, and snippets.

@ryanhall07
Created March 27, 2019 01:36
Show Gist options
  • Select an option

  • Save ryanhall07/e3eac6d2d47b72a4c37bce87219d7ced to your computer and use it in GitHub Desktop.

Select an option

Save ryanhall07/e3eac6d2d47b72a4c37bce87219d7ced to your computer and use it in GitHub Desktop.
Guice Circular Dependency Issues
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import java.util.Objects;
import javax.inject.Inject;
import javax.inject.Provider;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Java6Assertions.assertThatThrownBy;
public class FooTest {
/**
* Guice can correctly detect the circular dependency when a Provider<Bar> is used in the
* Foo Provider. This is because circular dependencies are only detected when attempting
* to construct objects.
*/
@Test public void circularDependency() {
AbstractModule module = new AbstractModule() {
@Override protected void configure() {
binder().disableCircularProxies();
bind(Foo.class).toProvider(new Provider<>() {
@Inject Provider<Bar> bar;
@Override public Foo get() {
Objects.requireNonNull(bar.get());
return new Foo();
}
});
}
};
Injector injector = Guice.createInjector(module);
assertThatThrownBy(() -> injector.getInstance(Foo.class))
.hasMessageContaining("Found a circular dependency");
assertThatThrownBy(() -> injector.getInstance(Bar.class))
.hasMessageContaining("Found a circular dependency");
}
/**
* Guice fails to detect the circular dependency and blows up building the Injector when
* Bar is directly injected into the Foo Provider. This is because Guice is in the middle of
* building the Injector.
*
* Is it an anti pattern to construct objects in a Provider? Should they always be Providers?
*/
@Test public void noCircularDependency() {
AbstractModule module = new AbstractModule() {
@Override protected void configure() {
binder().disableCircularProxies();
bind(Foo.class).toProvider(new Provider<>() {
@Inject Bar bar;
@Override public Foo get() {
Objects.requireNonNull(bar, "bar was never initialized by guice!");
return new Foo();
}
});
}
};
assertThatThrownBy(() -> Guice.createInjector(module))
.hasMessageContaining("bar was never initialized by guice!");
}
static class Foo {
}
static class Bar {
@Inject Foo foo;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment