Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 334498

Summary: [DI] ContextInjectionFactory.make on nested class within @PostConstruct method of outer class leads to endless recursion
Product: [Eclipse Project] Platform Reporter: Paul Reuter <preuter>
Component: RuntimeAssignee: Oleg Besedin <ob1.eclipse>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: ob1.eclipse, remy.suen
Version: 4.1   
Target Milestone: 4.2 M1   
Hardware: PC   
OS: Mac OS X - Carbon (unsup.)   
Whiteboard:
Attachments:
Description Flags
Is this the problem?
none
Trying to duplicate
none
Patch none

Description Paul Reuter CLA 2011-01-17 04:28:35 EST
Build Identifier: I20101216-1305

This seems to be related to a JDK bug in Constructor.getGenericParameterTypes:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5087240

Is there a possible workaround?

Reproducible: Always

Steps to Reproduce:
1. Create nested class with @Inject annotated constructor
2. Within outer class in @PostConstruct annotated method, call ContextInjectionFactory.make(NestedClass.class, context)
Comment 1 Oleg Besedin CLA 2011-01-17 11:37:12 EST
Created attachment 186923 [details]
Is this the problem?

Can you attach sample code that causes endless recursion? I tried to follow your description but what I am getting is an InjectionException which is more-or-less what is expected, see the attached code.
Comment 2 Paul Reuter CLA 2011-01-18 01:29:54 EST
Ah, I found the reason your test case does not reproduce the bug:

in org.eclipse.e4.core.internal.di.InjectorImpl.internalMake:298
// unless this is the default constructor, it has to be tagged
if (!constructor.isAnnotationPresent(Inject.class) && constructor.getParameterTypes().length != 0)
	continue;


Adding @Inject to the constructor of the nested class does the trick for me.

The reason for the endless recursion is the following:

In org.eclipse.e4.core.internal.di.InjectorImpl.resolveArgs:391,

the argument descriptors returned by 

org.eclipse.e4.core.internal.di.ConstructorRequestor.getDependentObjects()

include the outer class as first argument, which is then later created, thereby triggering the @PostConstruct and subsequent endless recursion.
Comment 3 Paul Reuter CLA 2011-01-18 04:41:08 EST
On a related note, the necessity of the @Inject annotation on the default constructor is also a bug, I think. 

Since the default constructor of a nested class has the outer class as first parameter, it is not recognized as default constructor by the code-snippet above.
Comment 4 Oleg Besedin CLA 2011-01-18 10:08:00 EST
Created attachment 187005 [details]
Trying to duplicate

Hmm... I've added @Inject to constructor and still getting an injection exception, not an endless loop.
Comment 5 Paul Reuter CLA 2011-01-24 11:05:49 EST
Oh my, found some egg on my face. I never actually ran this bug in "Run" mode, which pops up an InjectionException after a few seconds (still outrageous for something so simple). 

In debug mode, this takes long enough that I never actually waited it out, so I did not realize the unspectacular ending.

Could you place a breakpoint in the @PostConstruct method and observe if you hit it more than the one time that is expected?
Comment 6 Oleg Besedin CLA 2011-06-20 11:56:58 EDT
Created attachment 198265 [details]
Patch
Comment 7 Oleg Besedin CLA 2011-06-24 09:39:52 EDT
Patch applied to CVS Head.
Comment 8 Oleg Besedin CLA 2011-06-24 09:40:23 EDT
Thanks Paul for taking time to figure this out!