-
1. Re: Constructor injection for application-scoped beans
adamw Nov 13, 2009 11:20 AM (in response to adamw)Ah! B must have also a no-arg constructor. Probably because of the proxy?
Adam
-
2. Re: Constructor injection for application-scoped beans
nickarls Nov 13, 2009 12:28 PM (in response to adamw)Yep, it's normalscoped and therfore proxied.
As a side-note, we are working on an extension for no-args-constructorless creation using Unsafe.allocateInstance() or ReflectionFactory.newConstructorForSerialization() if they are available on the CP.
-
3. Re: Constructor injection for application-scoped beans
gavin.king Nov 13, 2009 2:36 PM (in response to adamw)Yep, add a constructor, introduce an interface, or inject Instance<B> instead of B.
-
4. Re: Constructor injection for application-scoped beans
adamw Nov 14, 2009 1:05 PM (in response to adamw)Thanks for the answers. All three ways work ;)
One more question though. I understand why a proxy is injected instead of the bean when injecting an app-scoped bean into a req-scoped bean, or a bean from a narrower scope into a bean with a wider scope.
But why a proxy is needed when injecting an app-scoped bean into another app-scoped bean? Or one session-scoped bean into another session-scoped bean? They will always be serialized together.
Adam
-
5. Re: Constructor injection for application-scoped beans
nickarls Nov 14, 2009 2:10 PM (in response to adamw)Of course there could be optimizations but I think currently it's
just in case
;-). I guess the recieving injection point could be examined to see if it's really required... -
6. Re: Constructor injection for application-scoped beans
nickarls Nov 14, 2009 3:19 PM (in response to adamw)Of course there is the problem of A getting injected into B getting injected into C which is conversation scoped and then goes long-running...
-
7. Re: Constructor injection for application-scoped beans
gavin.king Nov 14, 2009 6:03 PM (in response to adamw)
But why a proxy is needed when injecting an app-scoped bean into another app-scoped bean? Or one session-scoped bean into another session-scoped bean? They will always be serialized together.Well, in some particular implementation of CDI that may be the case - indeed it will be the most common implementation - but it's certainly not something that the spec requires. Don't assume that CDI context is exactly the same thing as a servlet context with the same name. The spec doesn't say that.
Also, the proxy might be needed to deal with circularities. (A injects B which injects C which injects A.) Unlike JSR-330, JSR-299 does require the container to deal with circularities.
Now, of course, a certain CDI implementation, like Weld, doesn't need to actually insert a real proxy object in this case. It's permitted to optimize it away, as per spec section 6.5.5. But that's a non-portable optimization.
In more general terms, we needed a simple, portable rule to give to users. We didn't want a set of rules with lots of caveats about the respective scopes of the beans and the existence of circularities. We want to say
normal scoped beans need proxies
and be done. Otherwise the user ends up writing a bunch of code that depends upon the respective scopes of the beans, and that breaks when the scope of a bean changes. Yes, unfortunately breakage like this is still possible if you change from @Dependent to a normal scope :-(Does that make sense?
-
8. Re: Constructor injection for application-scoped beans
gavin.king Nov 14, 2009 6:08 PM (in response to adamw)By the way, it's a good question, and one I wrestled with. It's the kind of issue where you might do something different if you were designing a single implementation, instead of a specification, and didn't have to worry about portability issues.
-
9. Re: Constructor injection for application-scoped beans
gavin.king Nov 14, 2009 6:46 PM (in response to adamw)Lemme take a second stab, from a usecase point of view.
There are three possible reasons for wanting a normal-scoped bean:
- you're accessing it directly from EL
- you're sharing it between multiple clients
- its client has a different scope
Now, if none of 1,2,3 apply, and the bean has one client, with the same lifecycle, then just leave the bean with the default @Dependent scope. No proxy required, no scope annotation required, no constructor required.
Furthermore, we can forget case 1, since no proxy is required when a bean is called from EL.
In case 2, we have lots of potential for circularities, or for clients with a passivating scope, or for clients with a wider scope. If you're writing a bean that has various clients, you might as well just stick the constructor in, and forget about it.
Even in case 3, the client might have a passivating scope or a wider scope, so there are going to be a bunch of secret rules that the container has for deciding whether a proxy is really going to be required or not. I really don't want to expose you to those rules.
And I'm not sure that you're really able to distinguish between cases 2 and 3 when you create the bean. Once a bean is sitting in a normal scope, it's there for everyone to get at.
HTH
-
10. Re: Constructor injection for application-scoped beans
adamw Nov 16, 2009 8:41 AM (in response to adamw)Ah, I understand. So the app, req, sess, cov scopes are just normal scopes and are treated uniformly, as if they could be serialized any time; makes sense. (Although maybe here the
passivating
attribute could play a role? The beans can be serialized only if passivated is true, but yes, that's also an optimization :) ).Also I didn't notice that you could have circular dependencies (unlike in Seam, where this caused an exception). However from experiments it seems that the @PostConstruct method is called when a proxy is first used (from another @PostConstruct method), not when the bean is injected - maybe it would be good to put that into documentation.
Adam
-
11. Re: Constructor injection for application-scoped beans
gavin.king Nov 16, 2009 8:45 AM (in response to adamw)For normal-scoped beans it is the proxy that is injected. The actual bean instance could be instantiated lazily. However, that is up to the implementation.
-
12. Re: Constructor injection for application-scoped beans
adamw Nov 16, 2009 9:07 AM (in response to adamw)I see. I thought it's a way to try to partially solve the problem of calling lifecycle callbacks in the presence of circular dependencies, but your answer makes more sense ;).
Adam