Skip to content

Instantly share code, notes, and snippets.

@electrotype
Last active December 14, 2015 15:29
Show Gist options
  • Save electrotype/5108107 to your computer and use it in GitHub Desktop.
Save electrotype/5108107 to your computer and use it in GitHub Desktop.
Bug Guice - ConstructorInjector. Now using ProvisionListener.
import static org.junit.Assert.*;
import java.util.UUID;
import org.junit.Test;
import com.google.inject.AbstractModule;
import com.google.inject.Binding;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.google.inject.matcher.AbstractMatcher;
import com.google.inject.spi.ProvisionListener;
public class ExampleTest
{
public static class ClassAAA
{
private final String id;
private final boolean myParam;
private final IClassBBBFactory classBBBFactory;
private ClassBBB clasBBB;
@Inject
public ClassAAA(@Assisted boolean myParam,
IClassBBBFactory classBBBFactory)
{
this.myParam = myParam;
this.id = UUID.randomUUID().toString();
this.classBBBFactory = classBBBFactory;
}
public void init()
{
if(this.myParam)
{
this.clasBBB = this.classBBBFactory.create(UUID.randomUUID().toString());
}
}
public String getId()
{
return this.id;
}
public ClassBBB getClassBBB()
{
return this.clasBBB;
}
}
public static class ClassBBB
{
private final IClassAAAFactory classAAAFactory;
private ClassAAA clasAAACreatedByClassBBB;
@Inject
public ClassBBB(@Assisted String myParam,
IClassAAAFactory classAAAFactory)
{
this.classAAAFactory = classAAAFactory;
}
public void init()
{
// The problem is here. Even if the factory should return a new instance
// of ClassAAA, it returns the one that is creating ClassBBB!
this.clasAAACreatedByClassBBB = this.classAAAFactory.create(false);
}
public ClassAAA getClasAAACreatedByClassBBB()
{
return this.clasAAACreatedByClassBBB;
}
}
public static interface IClassAAAFactory
{
public ClassAAA create(boolean someParam);
}
public static interface IClassBBBFactory
{
public ClassBBB create(String someParam);
}
@Test
public void bugGuiceConstructorInjector()
{
Injector injector = Guice.createInjector(new AbstractModule()
{
@Override
protected void configure()
{
bindListener(new AbstractMatcher<Binding<?>>()
{
@Override
public boolean matches(Binding<?> t)
{
return ClassAAA.class.isAssignableFrom(t.getKey().getTypeLiteral().getRawType()) ||
ClassBBB.class.isAssignableFrom(t.getKey().getTypeLiteral().getRawType());
}
},
new ProvisionListener()
{
@Override
public <T> void onProvision(ProvisionInvocation<T> provision)
{
Object obj = provision.provision();
if(obj instanceof ClassAAA)
{
((ClassAAA)obj).init();
}
else if(obj instanceof ClassBBB)
{
((ClassBBB)obj).init();
}
}
});
install(new FactoryModuleBuilder().build(IClassAAAFactory.class));
install(new FactoryModuleBuilder().build(IClassBBBFactory.class));
}
});
IClassAAAFactory classAAAFactory = injector.getInstance(IClassAAAFactory.class);
ClassAAA classAAA = classAAAFactory.create(true);
// Shouldn't be the same id!
assertNotEquals(classAAA.getClassBBB().getClasAAACreatedByClassBBB().getId(), classAAA.getId());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment