CDI @Observes ApplicationScoped.class

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

CDI @Observes ApplicationScoped.class

tonywestonuk
Hi ,

Im using CDI1.1 initializers and destroyer methods:


@ApplicationScoped
public class MyService {

public void init(@Observes @Initialized(ApplicationScoped.class)  obj){
          System.out.println("***INIT "+System.identityHashCode(this));
}

public void destroy(@Observes @Destroyed(ApplicationScoped.class)  obj){
          System.out.println("***Destroy "+System.identityHashCode(this));
}

}


In the logs, it shows different identityHashCodes, even though MyService is ApplicationScoped.
This causes problems if I need to clean up instance variables.

Is this a bug?  Or, should I tidy up instance variables in a different way? I dont really like using static variables.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: CDI @Observes ApplicationScoped.class

Romain Manni-Bucau
Hi

it depends the type, if the ServletContext for a war it should be the same
- even if the spec doesn't require it. Can you print the instance you get
just to ensure?

In any case you have MyService being application scoped so you can store
any state there without any static variable.


Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://blog-rmannibucau.rhcloud.com> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | JavaEE Factory
<https://javaeefactory-rmannibucau.rhcloud.com>

2017-05-29 10:18 GMT+02:00 tonywestonuk <[hidden email]>:

> Hi ,
>
> Im using CDI1.1 initializers and destroyer methods:
>
>
> @ApplicationScoped
> public class MyService {
>
> public void init(@Observes @Initialized(ApplicationScoped.class)  obj){
>           System.out.println("***INIT "+System.identityHashCode(this));
> }
>
> public void destroy(@Observes @Destroyed(ApplicationScoped.class)  obj){
>           System.out.println("***Destroy "+System.identityHashCode(this));
> }
>
> }
>
>
> In the logs, it shows different identityHashCodes, even though MyService is
> ApplicationScoped.
> This causes problems if I need to clean up instance variables.
>
> Is this a bug?  Or, should I tidy up instance variables in a different way?
> I dont really like using static variables.
>
>
>
>
> --
> View this message in context: http://tomee-openejb.979440.
> n4.nabble.com/CDI-Observes-ApplicationScoped-class-tp4681766.html
> Sent from the TomEE Users mailing list archive at Nabble.com.
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: CDI @Observes ApplicationScoped.class

tonywestonuk
This post was updated on .
MyService is an @ApplicationScoped bean

And, yet the identity hashcodes change between the init, and destroy methods.

Which means, I don't have access to the same instance variables in destory, that I constructed in the init.

This is the problem.


In my specific case, I am creating a UDP socket in init, storing it as an instance variable. And want to close it in destroy. However, the destroy method cant access the socket - crashes with null pointer.  I cant hot-redeploy as the UDP socket remains open. :-(


Try it for yourself - create a simple webapp, with this class.  And hot deploy / reload the app using tomee manager.  Check the logs.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: CDI @Observes ApplicationScoped.class

Romain Manni-Bucau
Just tested with tomee embedded this listener:

@ApplicationScoped
public static class Listener {
    public void start(@javax.enterprise.event.Observes
@Initialized(ApplicationScoped.class) Object start) {
        log(start);
    }
    public void end(@javax.enterprise.event.Observes
@Destroyed(ApplicationScoped.class) Object end) {
        log(end);
    }

    private void log(final Object event) {
        System.out.println();
        System.out.println(this);
        System.out.println(System.identityHashCode(this));
        System.out.println(event);
        System.out.println(System.identityHashCode(event));
        System.out.println();
    }
}


And got:

org.apache.tomee.embedded.ClasspathAsWebappTest$Listener@21c747a
35419258
org.apache.catalina.core.ApplicationContextFacade@77d4ac52
2010426450

org.apache.tomee.embedded.ClasspathAsWebappTest$Listener@1913053c
420676924
org.apache.catalina.core.ApplicationContextFacade@77d4ac52
2010426450

so looks good


Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://blog-rmannibucau.rhcloud.com> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | JavaEE Factory
<https://javaeefactory-rmannibucau.rhcloud.com>

2017-05-29 10:26 GMT+02:00 tonywestonuk <[hidden email]>:

>
> MyService is an @ApplicationScoped bean
>
> And, yet the identity hashcodes change between the init, and destroy
> methods.
>
> Which means, I don't have access to the same instance variables in destory,
> that I constructed in the init.
>
> This is the problem.
>
>
> In my specific case, I am creating a UDP socket in init, storing it as an
> instance variable. And want to close it in destroy. However, the destroy
> method cant access the socket - crashes with null pointer.  I cant
> hot-redeploy as the UDP socket remains open. :-(
>
>
>
>
>
> --
> View this message in context: http://tomee-openejb.979440.
> n4.nabble.com/CDI-Observes-ApplicationScoped-class-tp4681766p4681768.html
> Sent from the TomEE Users mailing list archive at Nabble.com.
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: CDI @Observes ApplicationScoped.class

Romain Manni-Bucau
oops, did a magic shortcut deleting half of the mail :s, sorry about it

here is the bean which works:

@ApplicationScoped
public static class Listener {
    private boolean init = false;
    public void start(@javax.enterprise.event.Observes
@Initialized(ApplicationScoped.class) Object start) {
        init = true;
        log(start);
    }

    @PreDestroy
    public void end() {
        System.out.println();
        System.out.println(this);
        System.out.println(System.identityHashCode(this));
        System.out.println(init);
        System.out.println();
    }

    private void log(final Object event) {
        System.out.println();
        System.out.println(this);
        System.out.println(System.identityHashCode(this));
        System.out.println(event);
        System.out.println(System.identityHashCode(event));
        System.out.println();
    }
}


And its output:


org.apache.tomee.embedded.ClasspathAsWebappTest$Listener@4e2916c3
1311315651
org.apache.catalina.core.ApplicationContextFacade@64aad6db
1688917723

org.apache.tomee.embedded.ClasspathAsWebappTest$Listener@4e2916c3
1311315651
true


The destroy event is fired once the bean was already destroyed it seems,
not a blocker clearly but will check why it breaks your case

Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://blog-rmannibucau.rhcloud.com> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | JavaEE Factory
<https://javaeefactory-rmannibucau.rhcloud.com>

2017-05-29 11:01 GMT+02:00 Romain Manni-Bucau <[hidden email]>:

> Just tested with tomee embedded this listener:
>
> @ApplicationScoped
> public static class Listener {
>     public void start(@javax.enterprise.event.Observes @Initialized(ApplicationScoped.class) Object start) {
>         log(start);
>     }
>     public void end(@javax.enterprise.event.Observes @Destroyed(ApplicationScoped.class) Object end) {
>         log(end);
>     }
>
>     private void log(final Object event) {
>         System.out.println();
>         System.out.println(this);
>         System.out.println(System.identityHashCode(this));
>         System.out.println(event);
>         System.out.println(System.identityHashCode(event));
>         System.out.println();
>     }
> }
>
>
> And got:
>
> org.apache.tomee.embedded.ClasspathAsWebappTest$Listener@21c747a
> 35419258
> org.apache.catalina.core.ApplicationContextFacade@77d4ac52
> 2010426450
>
> org.apache.tomee.embedded.ClasspathAsWebappTest$Listener@1913053c
> 420676924
> org.apache.catalina.core.ApplicationContextFacade@77d4ac52
> 2010426450
>
> so looks good
>
>
> Romain Manni-Bucau
> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> <https://blog-rmannibucau.rhcloud.com> | Old Blog
> <http://rmannibucau.wordpress.com> | Github
> <https://github.com/rmannibucau> | LinkedIn
> <https://www.linkedin.com/in/rmannibucau> | JavaEE Factory
> <https://javaeefactory-rmannibucau.rhcloud.com>
>
> 2017-05-29 10:26 GMT+02:00 tonywestonuk <[hidden email]>:
>
>>
>> MyService is an @ApplicationScoped bean
>>
>> And, yet the identity hashcodes change between the init, and destroy
>> methods.
>>
>> Which means, I don't have access to the same instance variables in
>> destory,
>> that I constructed in the init.
>>
>> This is the problem.
>>
>>
>> In my specific case, I am creating a UDP socket in init, storing it as an
>> instance variable. And want to close it in destroy. However, the destroy
>> method cant access the socket - crashes with null pointer.  I cant
>> hot-redeploy as the UDP socket remains open. :-(
>>
>>
>>
>>
>>
>> --
>> View this message in context: http://tomee-openejb.979440.n4
>> .nabble.com/CDI-Observes-ApplicationScoped-class-tp4681766p4681768.html
>> Sent from the TomEE Users mailing list archive at Nabble.com.
>>
>
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: CDI @Observes ApplicationScoped.class

Romain Manni-Bucau
Ok,

spec says:

"an event with qualifier @Destroyed(X.class) when a custom context is
destroyed, i.e. after the actual destruction,"

So we are sadly good and you need to use the @PreDestroy trick

Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://blog-rmannibucau.rhcloud.com> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | JavaEE Factory
<https://javaeefactory-rmannibucau.rhcloud.com>

2017-05-29 11:05 GMT+02:00 Romain Manni-Bucau <[hidden email]>:

> oops, did a magic shortcut deleting half of the mail :s, sorry about it
>
> here is the bean which works:
>
> @ApplicationScoped
> public static class Listener {
>     private boolean init = false;
>     public void start(@javax.enterprise.event.Observes @Initialized(ApplicationScoped.class) Object start) {
>         init = true;
>         log(start);
>     }
>
>     @PreDestroy
>     public void end() {
>         System.out.println();
>         System.out.println(this);
>         System.out.println(System.identityHashCode(this));
>         System.out.println(init);
>         System.out.println();
>     }
>
>     private void log(final Object event) {
>         System.out.println();
>         System.out.println(this);
>         System.out.println(System.identityHashCode(this));
>         System.out.println(event);
>         System.out.println(System.identityHashCode(event));
>         System.out.println();
>     }
> }
>
>
> And its output:
>
>
> org.apache.tomee.embedded.ClasspathAsWebappTest$Listener@4e2916c3
> 1311315651
> org.apache.catalina.core.ApplicationContextFacade@64aad6db
> 1688917723
>
> org.apache.tomee.embedded.ClasspathAsWebappTest$Listener@4e2916c3
> 1311315651
> true
>
>
> The destroy event is fired once the bean was already destroyed it seems,
> not a blocker clearly but will check why it breaks your case
>
> Romain Manni-Bucau
> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> <https://blog-rmannibucau.rhcloud.com> | Old Blog
> <http://rmannibucau.wordpress.com> | Github
> <https://github.com/rmannibucau> | LinkedIn
> <https://www.linkedin.com/in/rmannibucau> | JavaEE Factory
> <https://javaeefactory-rmannibucau.rhcloud.com>
>
> 2017-05-29 11:01 GMT+02:00 Romain Manni-Bucau <[hidden email]>:
>
>> Just tested with tomee embedded this listener:
>>
>> @ApplicationScoped
>> public static class Listener {
>>     public void start(@javax.enterprise.event.Observes @Initialized(ApplicationScoped.class) Object start) {
>>         log(start);
>>     }
>>     public void end(@javax.enterprise.event.Observes @Destroyed(ApplicationScoped.class) Object end) {
>>         log(end);
>>     }
>>
>>     private void log(final Object event) {
>>         System.out.println();
>>         System.out.println(this);
>>         System.out.println(System.identityHashCode(this));
>>         System.out.println(event);
>>         System.out.println(System.identityHashCode(event));
>>         System.out.println();
>>     }
>> }
>>
>>
>> And got:
>>
>> org.apache.tomee.embedded.ClasspathAsWebappTest$Listener@21c747a
>> 35419258
>> org.apache.catalina.core.ApplicationContextFacade@77d4ac52
>> 2010426450
>>
>> org.apache.tomee.embedded.ClasspathAsWebappTest$Listener@1913053c
>> 420676924
>> org.apache.catalina.core.ApplicationContextFacade@77d4ac52
>> 2010426450
>>
>> so looks good
>>
>>
>> Romain Manni-Bucau
>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>> <https://blog-rmannibucau.rhcloud.com> | Old Blog
>> <http://rmannibucau.wordpress.com> | Github
>> <https://github.com/rmannibucau> | LinkedIn
>> <https://www.linkedin.com/in/rmannibucau> | JavaEE Factory
>> <https://javaeefactory-rmannibucau.rhcloud.com>
>>
>> 2017-05-29 10:26 GMT+02:00 tonywestonuk <[hidden email]>:
>>
>>>
>>> MyService is an @ApplicationScoped bean
>>>
>>> And, yet the identity hashcodes change between the init, and destroy
>>> methods.
>>>
>>> Which means, I don't have access to the same instance variables in
>>> destory,
>>> that I constructed in the init.
>>>
>>> This is the problem.
>>>
>>>
>>> In my specific case, I am creating a UDP socket in init, storing it as an
>>> instance variable. And want to close it in destroy. However, the destroy
>>> method cant access the socket - crashes with null pointer.  I cant
>>> hot-redeploy as the UDP socket remains open. :-(
>>>
>>>
>>>
>>>
>>>
>>> --
>>> View this message in context: http://tomee-openejb.979440.n4
>>> .nabble.com/CDI-Observes-ApplicationScoped-class-tp4681766p4681768.html
>>> Sent from the TomEE Users mailing list archive at Nabble.com.
>>>
>>
>>
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: CDI @Observes ApplicationScoped.class

tonywestonuk
This post was updated on .
In reply to this post by Romain Manni-Bucau


@preDestroy trick?    with CDI1.1.   Ok :-o

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: CDI @Observes ApplicationScoped.class

tonywestonuk
Thanksyou! :-D

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: CDI @Observes ApplicationScoped.class

Romain Manni-Bucau
In reply to this post by tonywestonuk
2017-05-29 10:56 GMT+02:00 tonywestonuk <[hidden email]>:

> Does it?
>
> The events are the same...  (Both 2010426450)
>

yes, in case of a way you can put state in the ServletContext


>
> HOWEVER,
> There are 2 separate instances of Listener (ref 35419258 and 420676924),
> even though Listener class is annotated with @ApplicationScoped
>
>
> So, the end method, will not be able to access the instance variables
> created in start.
>
> Is this really the way it should be?  If so, I'll have to use static
> variables.
>

It is as it should be since the spec requires the @Destroyed event to be
fired after the context destruction (got clarified in 2.0 work which added
a @BeforeDestroyed one)

However as said before you don't need to use static variables since you
have @PreDestroy which is a natural fit


>
>
>
>
>
>
> --
> View this message in context: http://tomee-openejb.979440.
> n4.nabble.com/CDI-Observes-ApplicationScoped-class-tp4681766p4681772.html
> Sent from the TomEE Users mailing list archive at Nabble.com.
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: CDI @Observes ApplicationScoped.class

Mark Struberg-2
+1

NO @Destroyed(SomeContext.class) can be observed in a bean with scope @SomeContext!
I even suggest we throw a ContextNotActive in the future.

You can observe the @Destroyed(ApplicationScoped.class) in an Extension.

But most of the time a @PreDestroy in your @ApplicationScoped bean would work much better!
Would that work for you?

LieGrue,
strub


> Am 29.05.2017 um 11:12 schrieb Romain Manni-Bucau <[hidden email]>:
>
> 2017-05-29 10:56 GMT+02:00 tonywestonuk <[hidden email]>:
>
>> Does it?
>>
>> The events are the same...  (Both 2010426450)
>>
>
> yes, in case of a way you can put state in the ServletContext
>
>
>>
>> HOWEVER,
>> There are 2 separate instances of Listener (ref 35419258 and 420676924),
>> even though Listener class is annotated with @ApplicationScoped
>>
>>
>> So, the end method, will not be able to access the instance variables
>> created in start.
>>
>> Is this really the way it should be?  If so, I'll have to use static
>> variables.
>>
>
> It is as it should be since the spec requires the @Destroyed event to be
> fired after the context destruction (got clarified in 2.0 work which added
> a @BeforeDestroyed one)
>
> However as said before you don't need to use static variables since you
> have @PreDestroy which is a natural fit
>
>
>>
>>
>>
>>
>>
>>
>> --
>> View this message in context: http://tomee-openejb.979440.
>> n4.nabble.com/CDI-Observes-ApplicationScoped-class-tp4681766p4681772.html
>> Sent from the TomEE Users mailing list archive at Nabble.com.
>>

Loading...