[cdi-dev] Proxy implementation leaks
Pete Muir
pmuir at redhat.com
Mon May 9 11:32:46 EDT 2011
You can't enhance the class without either a javaagent or bytecode instr.
If you use subclassing you only need to call the ctor of the superclass once, not twice as it stands today.
On 9 May 2011, at 16:30, Mark Struberg wrote:
> was about to ask the same ;)
>
> If there is some subclassing involved, then you will need to call the constructor of the superclass. You cannot solve this another way without changing the original class.
>
> There is only one magic trick, but this is a pretty heavyweight one:
> 1.) dynamically create an interface with all the methods from the class hierarchy from the proxied class
> 2.) create a java.lang.reflect.proxy for the interface
> 3.) dynamically _change_ the original proxied class to additionally implement the freshly generated interface
>
> This is pretty much work, but imo the only way which works.
> The downsides are that you need to 'enhance' the original class, which might cause ClassCastExceptions and lots of other nasty problems...
>
> LieGrue,
> strub
>
> --- On Mon, 5/9/11, Arne Limburg <arne.limburg at openknowledge.de> wrote:
>
>> From: Arne Limburg <arne.limburg at openknowledge.de>
>> Subject: AW: [cdi-dev] Proxy implementation leaks
>> To: "Pete Muir" <pmuir at redhat.com>, "Mark Struberg" <struberg at yahoo.de>
>> Cc: "cdi-dev at lists.jboss.org" <cdi-dev at lists.jboss.org>
>> Date: Monday, May 9, 2011, 3:26 PM
>> Hi Pete,
>>
>> how would you instantiate a client proxy, if not via a
>> constructor? You need one call for the proxy and one call
>> for the 'contextual instance'.
>> Or am I missing some available java-magic?
>>
>> Regards,
>> Arne
>>
>> -----Ursprüngliche Nachricht-----
>> Von: cdi-dev-bounces at lists.jboss.org
>> [mailto:cdi-dev-bounces at lists.jboss.org]
>> Im Auftrag von Pete Muir
>> Gesendet: Montag, 9. Mai 2011 17:20
>> An: Mark Struberg
>> Cc: cdi-dev at lists.jboss.org
>> Betreff: Re: [cdi-dev] Proxy implementation leaks
>>
>> Thanks Mark, I knew there was a reason for the lazy init.
>>
>> The two-ctor call is not necessary though.
>>
>> On 9 May 2011, at 16:15, Mark Struberg wrote:
>>
>>> actually this behaviour is pretty clear in EE. It's
>> the same thing as we have with EJBs since almost ever.
>> That's why @PostConstruct exists.
>>>
>>> Whenever object proxies or hidden/transparent
>> serialisation happens, then we need to create the
>> object/proxy on the other side/new invocation. And everytime
>> this happens, the constructer will obviously get called.
>>>
>>> So this is not a bug and surely not a leak!
>>>
>>> This was on our list when I did a talk about CDI
>> pitfalls at the JSFdays last year together with Dan.
>>>
>>> Maybe we should doument this better, but it's nothing
>> for the spec, but the user documentation imo.
>>>
>>> Also the lazy init is imo a well specified and welcome
>> behaviour. Look at the discussions way back about how to
>> prevent cyclic injection problems.
>>>
>>> LieGrue,
>>> strub
>>>
>>> --- On Mon, 5/9/11, Christian Bauer <christian.bauer at gmail.com>
>> wrote:
>>>
>>>> From: Christian Bauer <christian.bauer at gmail.com>
>>>> Subject: [cdi-dev] Proxy implementation leaks
>>>> To: cdi-dev at lists.jboss.org
>>>> Date: Monday, May 9, 2011, 2:46 PM
>>>> 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.
>>>>
>>>> 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.
>>>>
>>>>
>>>> _______________________________________________
>>>> cdi-dev mailing list
>>>> cdi-dev at lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>>
>>
>>
>> _______________________________________________
>> cdi-dev mailing list
>> cdi-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>
More information about the cdi-dev
mailing list