Alternative not selected in injection point when using SeContainerInitializer
vsevel Sep 14, 2018 7:31 AMHello,
I have been trying to play with SeContainerInitializer and encountered an issue.
I am using weld 3.0.2.Final
I have the following 2 beans in src/main/java :
public class BarImpl implements IBar {
@Inject
IFoo foo;
@PostConstruct
private void postConstruct() {
System.out.println("postConstruct BarImpl with foo=" + foo);
}
public String getId() {
return "bar";
}
@Override
public IFoo getFoo() {
return foo;
}
}
public class FooImpl implements IFoo {
@PostConstruct
private void postConstruct() {
System.out.println("postConstruct FooImpl");
}
public String getName() {
return "foo";
}
}
I declared an empty beans.xml in src/main/resources/META-INF/beans.xml :
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
In src/test/java I set up an alternative for the foo bean :
@Alternative
public class FooTestImpl implements IFoo {
@PostConstruct
private void postConstruct() {
System.out.println("postConstruct FooTestImpl");
}
@Override
public String getName() {
return "footest";
}
}
In my test I want to get the behavior of the alternative when I directly select it from the container, or get it from the injected field BarImpl.foo :
@Test
public void testCode() {
try (SeContainer container = SeContainerInitializer.newInstance()
// .disableDiscovery().addBeanClasses(FooImpl.class, BarImpl.class, FooTestImpl.class).selectAlternatives(FooTestImpl.class)
.addBeanClasses(FooTestImpl.class).selectAlternatives(FooTestImpl.class)
.initialize()) {
Instance<IFoo> fooInstance = container.select(IFoo.class);
IFoo foo = fooInstance.get();
Assert.assertEquals("footest", foo.getName());
Instance<IBar> barInstance = container.select(IBar.class);
IBar bar = barInstance.get();
Assert.assertEquals("bar", bar.getId());
IFoo fooFromBar = bar.getFoo();
Assert.assertEquals("footest", fooFromBar.getName());
}
}
the goal is to keep the discovery, but add the alternative.
with the above code, the test fails on the last assert : we get foo instead of footest.
If I do everything by hand:
.disableDiscovery().addBeanClasses(FooImpl.class, BarImpl.class, FooTestImpl.class).selectAlternatives(FooTestImpl.class)
then the 3 asserts pass.
digging into the code, I realized that there was a root manager instantiated that contained the alternative managed bean plus the BarImpl, but also another manager that seems to be instantiated solely from the beans.xml (so without the alternative). when BarImpl.foo gets injected, we get this second manager that does not know about the alternative, hence the behavior.
is that an expected behavior?
is there a way to combine a discovery with the ability to add a test alternative?
thanks,
vs.