On 9 May 2011, at 15:46, Christian Bauer wrote:
Started working with Weld 1.1.1 and found two issues that probably
should be addressed (maybe just documented). They both look to me like leaking
implementation details because proxies are used for components which are not @Singleton or
@Dependent.
@ApplicationScoped
public class Bug {
public Bug() {
System.out.println("########## CONSTRUCT");
}
public void foo() {
System.out.println("##### FOO");
}
public static void main(String[] args) {
Weld weld = new Weld();
WeldContainer weldContainer = weld.initialize();
Bug bug = weldContainer.instance().select(Bug.class).get(); // Creates new instance
of Bug
bug.foo(); // Creates new instance of Bug!!!
bug.foo(); // Uses existing instance
weld.shutdown();
}
}
The proxy of Bug will call its superclass constructor several times during the lifecycle
of the Bug component. I don't know if that is really necessary, but if it is, you can
now no longer use constructors to initialize your component. This is an issue because
- it's not documented that constructors of @ApplciationScoped (etc., proxied)
components behave differently than @Singleton/@Dependent constructors
- even if it's documented, it's questionable if that really should be the case.
Taking away constructors as the primary means of initializing a component - e.g.
obtaining resources such as database connections, reading config files, etc. - is a major
change in the Java programming model. Users have to be strongly advised to use
@PostConstruct then.
Stuart, I though subclassing proxies should resolve this?
The other issue I immediately found is also related to behavior of proxies and how
transitive initializing/injection is implemented (not sure if this is actually specified
somewhere):
@ApplicationScoped
public class Foo {
@Inject
Bar bar;
}
@ApplicationScoped
public class Bar {
@Inject
Baz baz;
@PostConstruct
void init() { ... }
}
When I obtain a reference to Foo, I get a proxy of Foo with a reference to a proxy of
Bar. The init() method of Bar is never called. The Baz component is never activated.
This means I can't transitively initialize an application-scoped graph of components.
I was trying to use CDI for wiring in a Swing application and I imagine this would be a
common usecase. It should either be documented that there is a difference between
@Singleton/@Dependent and proxy-implemented scopes, or unification should be considered.
The init of bar will happen lazily upon first call to a method of Foo. I never loved this
behavior but never found a better alternative.