users@glassfish.java.net

Re: _at_Startup _at_Singleton injection behavior question

From: Noah White <emailnbw_at_gmail.com>
Date: Tue, 5 Feb 2013 21:39:21 -0500

On Feb 5, 2013, at 8:00 PM, Marina Vatkina <marina.vatkina_at_oracle.com> wrote:

> Interesting... To get attention to the log4j question, it can be better to start a separate thread with another subject.

Noted.

>
> The PostConstruct method declared on the bean itself should be called last, so if any exception is thrown earlier, it's not reached.

Case cracked a little more. I'd placed a break point on the first line of @PostConstruct of the @Startup @Singleton EJB and on the first line of the @PostConstruct of the @ApplicationScoped CDI bean. It appears that @PostConstruct on the injected CDI bean is being called by a different thread then the thread calling @PostConstruct on the EJB.

Even though I have break points on the first lines of both methods it only breaks in the EJB and the CDI bean @PostConstruct parties on behind the scenes eventually calling the method which throws the exception. Once I was able to unmask the log statements in the CDI bean which were being eaten by log4j I could clearly see that. I verified by removing the break point from the EJB and observing the break point in the @PostConstruct of the CDI bean is hit. The debugger behavior in this case is a bit odd since in other multi-threaded situations I have observed the debugger to observe all break points and switch thread contexts as the break points are reached whilst stepping through them.

Fun times, thanks for your thoughts,

-Noah

>
> HTH,
> -marina
>
> On 2/5/13 3:54 PM, Noah White wrote:
>> OK - case cracked, for the most part.
>>
>> So what was happening was that @PostConstruct on the CDI bean was being called and it was throwing an exception leading to the object the getter was returning to be NULL.
>>
>> The logging of the exception was being eaten though because the web app uses log4j and for some reason during this point in the deployment lifecycle log4j is not properly initialized. I had a hunch about this and changed the logging over the JUL for this CDI bean et voila I could see the errors in the server.log.
>>
>> I would love to see a clean way, on a per app basis, of integrating log4j into GF but from what I have read so far there isn't. If anyone can point me to details on how to do this cleanly on a per app basis I am all ears. Bonus points for a clean SLF4J/logback integration on a per app basis (all jars and config files packaged and deployed w/the WAR).
>>
>> The other interesting thing, and I don't have an explanation for this, is that the break point I had set in the @PostConstruct method of the CDI bean (first line that can't be missed) never gets tripped. I would have expected to see it tripped when the container calls this method but I doesn't.
>>
>> -Noah
>>
>> On Feb 5, 2013, at 6:14 PM, Marina Vatkina <marina.vatkina_at_oracle.com> wrote:
>>
>>> Hi Noah,
>>>
>>> This is strange. Does it make a difference if it's an application scope bean or not? Feel free to file a bug.
>>>
>>> -marina
>>>
>>> On 2/5/13 3:10 PM, Noah White wrote:
>>>> Hi Marina,
>>>>
>>>> Nothing fancy along those lines is going on here. This @ApplicationScoped bean is simply responsible for providing some preferences which it initializes in its @PostConstruct. It is injected all over the place, including in this @Startup @Singleton. As a test I disable the EJB and observed the @PostConstruct method on the CDI bean is called when it is being injected into a ServletContextListener so I don't think that is the case. It feels like it is I think this is EJB/CDI lifecycle related.
>>>>
>>>> -Noah
>>>>
>>>> On Feb 5, 2013, at 5:37 PM, Marina Vatkina <marina.vatkina_at_oracle.com> wrote:
>>>>
>>>>> May be PostConstruct interceptor is not enabled for the CDI bean?
>>>>>
>>>>> -marina
>>>>> On 2/5/13 2:26 PM, Noah White wrote:
>>>>>> I have a @Startup @Singleton EJB which injects an @ApplicationScoped CDI bean which is used by the EJB's @PostConstruct method. It calls a getter on this @ApplicationScoped bean and is getting back NULL.
>>>>>>
>>>>>> What's interesting is the object returned by the @ApplicationScoped bean's getter is constructed in its @PostConstruct method. It appears @PostConstruct is not being called in this case. The @ApplicationScoped bean itself does not inject any resources.
>>>>>>
>>>>>> Is this a bug or by design? If by design could you point me to the spec reference? Thanks,
>>>>>>
>>>>>> -Noah
>>>>>>
>>>>>> Environment is gf: 3.1.2 b23
>