2

I use JSF viewscope for my managedbean. I call the managed bean in a html view.

When the page is refresh, there is a new managed bean allowed and the old one stay in the memory. If I refresh and refresh and refresh... I have got a huge number of the managed beans in the memory.
I try to run garbage collector, nothing append. The managed beans stay until the session expired. At the end of session, by user action or timeout, the managed bean are freed.

I only have this problem when I stay on the same page (refresh on the browser -F5- or redirection link without JSP tag or java code redirection). When I change page, there is only one managed bean freed (the last one). The others stay in the memory. It seme to work with JSP tag, the managed bean are freed after the redirection.

Second Bug : Some time I arrived in strange case : I have some managed bean not freed in memory, I use JSP tag redirect (may 3/4 times) and the system do Predestroy / PostConstruct / Predestroy... And after that every redirection do PostConstruct / Predestroy for not JSP tag or java redirection, Predestroy / PostConstruct / Predestroy for JSP tag. In the memory a managed bean not freed is freed after that. I realy don't know what is realy the case reproduce this, but it do multiple time.

Do somebody have some solution for this problems ? I see a post look like problem here and I report a bug on java.net

Configuration : Java EE 7 / glassfish 4

AViewscope.java :

package com.btm.viewscopetest;

import java.io.IOException;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

@ManagedBean
@ViewScoped
public class AViewscope implements Serializable {

    @PostConstruct
    public void postConstruct() {
        System.out.println("PostConstruct");
    }

    @PreDestroy
    public void preDestroy() {
        System.out.println("PreDestroy");
    }

    public AViewscope() {
    }

    public String getSomething() {
        return "Something";
    }

    public void redirect() throws IOException {
        FacesContext facesContext = FacesContext.getCurrentInstance();

        ExternalContext externalContext = facesContext.getExternalContext();

        externalContext.redirect("apage.xhtml");
    }
}

apage.xhtml :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
    <head>
        <title>A page</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    </head>
    <body>
        <h:form>
            <h:outputText value="Get something: #{aViewscope.something}" />

            <br/>
            <br/>

            <h:commandButton value="Stay on this page with java " actionListener="#{aViewscope.redirect}"/>
            <br/>
            <h:commandButton value="Stay on this page with direct link" action="apage" />
            <br/>
            <h:commandButton value="Go to another page" action="anotherPage"/>
            <br/>
            <h:commandLink value="Stay on this page with direct link h tag " action="apage.xhtml" />
            <a href="apage.xhtml">Stay on this page with direct link a tag</a>
        </h:form>

    </body>
</html>

anotherPage.xhtml :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
    <head>
        <title>Another Page</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    </head>
    <body>
        <h:form>
            <h:commandButton value="Go to another page" action="apage"/>
        </h:form>

    </body>
</html>

web.xml :

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>index.xhtml</welcome-file>
    </welcome-file-list>
</web-app>
Community
  • 1
  • 1
user3805731
  • 275
  • 2
  • 3
  • 13
  • Duplicate: https://stackoverflow.com/questions/20930396/why-are-expired-viewscoped-beans-not-destroyed-until-the-session-expires (and there are more similar posts on SO, please search for them and reference them – Kukeltje Jul 24 '15 at 10:39
  • I already see that post (I give the reference in my question). That is not realy tell me how to corect my problem... And sadly I can't use omnifaces in my project. – user3805731 Jul 24 '15 at 16:21
  • Sorry, because of all the text befor it, stopped reading since I remembered this link. Next time it is better to post these earlier in your question – Kukeltje Jul 24 '15 at 16:23
  • ok. Do you have some idea to solve it ? – user3805731 Jul 24 '15 at 16:41
  • Well, there are more posts on SO. Some related the views in session. So maybe they are not released as stated in the answer – Kukeltje Jul 24 '15 at 16:52
  • Memory leak? Are you implying that the bean is not destroyed when the associated HTTP session is destroyed? – BalusC Jul 27 '15 at 08:07
  • @BalusC Beans are destroyed at the end of HTTP session. – user3805731 Jul 28 '15 at 07:58
  • Then there's no memory leak. – BalusC Jul 28 '15 at 08:25
  • @BalusC well well well... You're right ! Cycle life problem if you prefer... Any solution ? – user3805731 Jul 28 '15 at 16:02

1 Answers1

1

I have got a huge number of the managed beans in the memory. I try to run garbage collector, nothing append

This is not a bug, it's intentional. JSF maintains a certain number of beans in the memory, if your javax.faces.STATE_SAVING_METHOD is set to server in the web.xml. The client will now always submit a javax.faces.ViewState (id), allowing the server to identify the proper beans to load.

You can limit the amount of views stored per session, by setting the context-param com.sun.faces.numberOfViewsInSession to a number that matches your needs.

But be aware that if you choose 1, and the user use backwards navigation he will encounter ViewExpired exceptions if the bean has been removed.

Another option to decrease memory load would be to handle the view-storage over to the client, by setting javax.faces.STATE_SAVING_METHOD to client. However this will lead to increased network traffic, because now the client does not only need to have a javax.faces.ViewState to track - but the whole view itself. I'm not one hundred percent sure how exactly the client-option works, but to me it feels dangerous to let a client keep track of the "View" rather than just the identifier.

dognose
  • 20,360
  • 9
  • 61
  • 107
  • How can you tell "it's intentional" ? (not sarcastic, it's a real question) If it's intentional, why when I use JSP tag, the managed bean is freed ? And why do when I am in normal navigation (a page to another page), the managed bean is free ? I understand the principle of reuse managed to not loose time of alocate memory (pool memory) but to me we are not in this case. I try `javax.faces.STATE_SAVING_METHOD` and `com.sun.faces.numberOfViewsInSession` , I try and retry this method that is not working. Do you try it ? – user3805731 Jul 24 '15 at 16:39