Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@PreDestroy not called after session expired

This is a JSF 2 app running on WAS8.0. Here is the code for the "backing" bean of one page.

    @Named("mySessionBean")
    @SessionScoped
    @Stateful
    @LocalBean
    @StatefulTimeout(unit = TimeUnit.MINUTES, value = 10)
    public class MySessionBean implements Serializable {
        @PostConstruct
        public void init()
        {
             System.out.println("start MySessionBean: " + this.hashCode());
         }

        @PreDestroy
        public void cleanup()
        {
             System.out.println("destroy MySessionBean: " + this.hashCode());
         }
        ....
    }

The session timeout value set in web.xml is smaller than the bean's timeout. When I run the app, I see the printout from @PostConstruct but never see the one from @PreDestroy. I have tried the following 2 scenarios: 1. logout - invalidateSession; 2. simply wait until the session expires.

I'm not the designer of the app. The designer insists to make all the backing bean as a stateful session bean. I think the more mainstream approach would be just making them CDI bean. But anyway, when I do change the annotation to CDI only, I start getting the printout from @PreDestroy as well

    @Named("mySessionBean")
    @SessionScoped
    public class MySessionBean implements Serializable {
    .....

My question is, what is the reason that I'm not getting the @PreDestroy method call in the first case? If I can't see the @PreDestroy get called, is there any other ways that I can trace the lifecycle of the "backing" beans (in this case, a stateful session bean). Thanks!

like image 494
chaoshangfei Avatar asked Feb 06 '13 22:02

chaoshangfei


2 Answers

Look at this section of the Java EE 6 Tutorial, it shows the lifecycle of stateful session beans. The PreDestroy method is only called when the bean is explicitly removed from the client code, calling a method annotated with @Remove.

like image 57
remigio Avatar answered Sep 18 '22 18:09

remigio


The other answer links to a Java EE 6 Tutorial, that doesn't even mention the existence of timeouts. I also don't think that tutorial clearly states that @PreDestroy method is only called after an explicit @Remove method call. The causation is not stated, it just describes two events, not necessarily directly related:

At the end of the lifecycle, the client invokes a method annotated @Remove, and the EJB container calls the method annotated @PreDestroy, if any.

The WebSphere docs mention the following:

The PreDestroy life cycle interceptor callbacks are invoked for a stateful session bean when a remove method is called. Also keep in mind that the PreDestroy life cycle interceptor callbacks are not called if the stateful session bean times out while in the passive state, or if an unexpected exception occurs during a method invocation on the bean and the bean is discarded.

Now here it does clearly state that PreDestroy callbacks are invoked when a remove method is called. At the same time it explictly states that PreDestroy callbacks are not called if the SFSB times out while in the passive state. So that would mean they do get called when the SFSB is not in the passive state?

Now let's take a look at JBoss.
First, there's a JBoss issue about PreDestroy not being called on removal timeout if removalTimeout < idleTimeout. Seems to be fixed in 5.2.
Second, I just tested on JBoss 4.3, what happens when a passivated SFSB gets removed on timeout - it gets activated before destroying.

So it seems that there exist multiple interpretations of how timeouts and bean removal should behave.

like image 21
Vsevolod Golovanov Avatar answered Sep 21 '22 18:09

Vsevolod Golovanov