Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

jsf 2 - JSF 2.1 ViewScopedBean @PreDestroy method is not called

I have a method in a view Scoped Bean with the @PreDestroy annotation and another one with the @PostConstruct annotation.

The @PostConstruct method is properly called every time I navigate to the page that uses this view scoped bean.

However, when I navigate to a new page (which doesn't use this view scope bean) by <h:link/>, the @PreDestroy method is never called.

I am not talking about changing manually the url or the end of the session, just of a navigation case.

What I am missing?

Thanks in advance

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This is by design. It will only be destoyed immediately when a POST action results in a navigation which isn't a postback to the same view (i.e. the action method didn't return null or void, but a fullworthy String, even when just empty).

The <h:link> generates a GET link which doesn't invoke any POST action. As it's not reliably possible to notify the server side by a (XML)HTTP request when the view is unloaded, JSF can't be notified to destroy the view scoped bean associated with the view. In such case, the view scoped bean will then only be destroyed when the session expires or when the max logical views in session has exceeded (the default is 15) and the associated view is the first in order.

If you really want to destoy the view scoped bean by a navigaiton action, then your best bet is to make it a POST request by <h:commandLink> instead and issue a redirect by returning the navigation outcome with ?faces-redirect=true parameter. But this is after all not SEO friendly as bots won't index POST links.

I would after all not care about the view still being in the session. If you intend to do some cleanup or logging, I'd look for alternative ways, depending on the concrete functional requirement.

In theory it would be possible by HTML DOM onbeforeunload event, but this is a non-standard event and the browser behaviour is unspecified as to what happens when you send an ajax request during that event. It will sometimes arrive, but sometimes also not.

Update: in practice, this has been implemented in OmniFaces @ViewScoped since OmniFaces 2.2. Initially with help of synchronous XHR and since OmniFaces 2.6 with help of beacon. It's working quite well in major browsers. Since OmniFaces 2.3 it even immediately destroys the associated JSF server side view state, and since OmniFaces 2.6 it even immediately destroys the physical beans, hereby further reducing unnecessary memory usage. See also among others JSF: Mojarra vs. OmniFaces @ViewScoped: @PreDestroy called but bean can't be garbage collected


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share

2.1m questions

2.1m answers

63 comments

56.7k users

...