2012-03-27 9 views
2

Ich versuche, ein einzelnes SFSB in einer ViewScoped JSF-Backing-Bean in Glassfish 3.1.1 zu injizieren.Überflüssiges SFSB, das in Glassfish erstellt wird und daher Speicher verliert

Mein Protokoll zeigt dies, das ist, dass zwei SFSBs erstellt werden, obwohl nur der zweite injiziert wird:

INFO: constructed a new sfsb: [email protected] 
INFO: constructed a new sfsb: [email protected]e 
INFO: constructed a new view scoped bean: [email protected] 

Später, als ich weg navigieren und die ViewScoped Bohne geht out of scope, entferne ich aufrufen () auf der SFSB, und so sehe ich dies im Protokoll:

INFO: destroying view scoped bean: [email protected] 
INFO: removing sfsb: [email protected]e 
INFO: destroying sfsb: [email protected]e 

Aber die überflüssige erstes in @ f48cde0 Endung wurde nie eingespritzt, so habe ich nicht einen Griff, um es, und es wird nie entfernt . Erst später, als ich den Server heruntergefahren habe, sehe ich, dass er entfernt wird.

ist hier mein Code:

Die Backing Bean:

package com.example.test.ui; 

import java.io.Serializable; 
import java.util.logging.Logger; 

import javax.annotation.PostConstruct; 
import javax.annotation.PreDestroy; 
import javax.ejb.EJB; 
import javax.faces.bean.ManagedBean; 
import javax.faces.bean.ViewScoped; 
import javax.faces.event.AjaxBehaviorEvent; 

import com.example.test.service.api.TestSFSB; 

@ManagedBean(name = "testViewScopedSFSB") 
@ViewScoped 
public class TestViewScopedSFSB implements Serializable { 

    private static final long serialVersionUID = 1L; 
    private static final Logger LOGGER = Logger.getLogger(TestViewScopedSFSB.class.getCanonicalName()); 

    @EJB 
    private TestSFSB testSFSB; 

    @PostConstruct 
    public void postConstruct() { 
    LOGGER.info("constructed a new view scoped bean: " + this); 
    } 

    public int getNumClicks() { 
    return testSFSB.getNumClicks(); 
    } 

    public void clicked(AjaxBehaviorEvent event) { 
    testSFSB.clicked(); 
    } 

    @PreDestroy 
    public void preDestroy() { 
    LOGGER.info("destroying view scoped bean: " + this); 
    testSFSB.remove(); 
    } 

} 

Die SFSB Schnittstelle:

package com.example.test.service.api; 

public interface TestSFSB { 

    void clicked(); 

    int getNumClicks(); 

    void remove(); 

} 

Die SFSB Umsetzung:

package com.example.test.service.impl; 

import java.util.logging.Logger; 

import javax.annotation.PostConstruct; 
import javax.annotation.PreDestroy; 
import javax.ejb.Local; 
import javax.ejb.Remove; 
import javax.ejb.Stateful; 

import com.example.test.service.api.TestSFSB; 

@Stateful 
@Local(TestSFSB.class) 
public class TestSFSBImpl implements TestSFSB { 

    private static final long serialVersionUID = 1L; 
    private static final Logger LOGGER = Logger.getLogger(TestSFSBImpl.class.getCanonicalName()); 

    int numClicks = 0; 

    @PostConstruct 
    public void postConstruct() { 
    LOGGER.info("constructed a new sfsb: " + this); 
    } 

    @Override 
    public void clicked() { 
    numClicks++; 
    } 

    @Override 
    public int getNumClicks() { 
    return numClicks; 
    } 

    @Override 
    @Remove 
    public void remove() { 
    LOGGER.info("removing sfsb: " + this); 
    } 

    @PreDestroy 
    public void preDestroy() { 
    LOGGER.info("destroying sfsb: " + this); 
    } 

} 

Und schließlich die JSF-Seite:

<?xml version="1.0" encoding="ISO-8859-1" ?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<h:html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:c="http://java.sun.com/jsp/jstl/core" 
    xmlns:f="http://java.sun.com/jsf/core" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:ui="http://java.sun.com/jsf/facelets"> 

<h:head> 

</h:head> 

<h:body> 
    <h:form> 
     <h:commandLink action="/public/publicResource.jsf" value="Home" /> 
     <h:panelGrid id="panel1"> 
      <h:commandButton value="Click me"> 
       <f:ajax event="click" listener="#{testViewScopedSFSB.clicked}" 
        render="panel1" /> 
      </h:commandButton> 
      <h:outputText value="#{testViewScopedSFSB.numClicks}" /> 
     </h:panelGrid> 
    </h:form> 

</h:body> 
</h:html> 

Das ist so eine einfache Einrichtung ... was zum Teufel könnte es sein? Ein Fehler in Glassfish vielleicht?

EDIT: Um keine „Zweifel“ an der Richtigkeit zu beschwichtigen, was ich berichte, ist hier das Protokoll, wenn ich die Seite 10 mal laden. Anmerkung 20 SFSBs erstellt, jedes Mal 2, aber nur 1 aufgeräumt, wenn ich weg navigiere.

INFO: constructed a new sfsb: [email protected]9 
INFO: constructed a new sfsb: [email protected]9 
INFO: constructed a new view scoped bean: [email protected] 
INFO: destroying view scoped bean: [email protected] 
INFO: removing sfsb: [email protected]9 
INFO: destroying sfsb: [email protected]9 

INFO: constructed a new sfsb: [email protected]9 
INFO: constructed a new sfsb: [email protected]3 
INFO: constructed a new view scoped bean: [email protected] 
INFO: destroying view scoped bean: [email protected] 
INFO: removing sfsb: [email protected]3 
INFO: destroying sfsb: [email protected]3 

INFO: constructed a new sfsb: [email protected]7 
INFO: constructed a new sfsb: [email protected]7 
INFO: constructed a new view scoped bean: [email protected] 
INFO: destroying view scoped bean: [email protected] 
INFO: removing sfsb: [email protected]7 
INFO: destroying sfsb: [email protected]7 

INFO: constructed a new sfsb: [email protected]e 
INFO: constructed a new sfsb: [email protected]0 
INFO: constructed a new view scoped bean: [email protected] 
INFO: destroying view scoped bean: [email protected] 
INFO: removing sfsb: [email protected]0 
INFO: destroying sfsb: [email protected]0 

INFO: constructed a new sfsb: [email protected]0 
INFO: constructed a new sfsb: [email protected] 
INFO: constructed a new view scoped bean: [email protected] 
INFO: destroying view scoped bean: [email protected] 
INFO: removing sfsb: [email protected] 
INFO: destroying sfsb: [email protected] 

INFO: constructed a new sfsb: [email protected]b 
INFO: constructed a new sfsb: [email protected]a 
INFO: constructed a new view scoped bean: [email protected] 
INFO: destroying view scoped bean: [email protected] 
INFO: removing sfsb: [email protected]a 
INFO: destroying sfsb: [email protected]a 

INFO: constructed a new sfsb: [email protected]8 
INFO: constructed a new sfsb: [email protected]f 
INFO: constructed a new view scoped bean: [email protected] 
INFO: destroying view scoped bean: [email protected] 
INFO: removing sfsb: [email protected]f 
INFO: destroying sfsb: [email protected]f 

INFO: constructed a new sfsb: [email protected]0 
INFO: constructed a new sfsb: [email protected]b 
INFO: constructed a new view scoped bean: [email protected] 
INFO: destroying view scoped bean: [email protected] 
INFO: removing sfsb: [email protected]b 
INFO: destroying sfsb: [email protected]b 

INFO: constructed a new sfsb: [email protected]5 
INFO: constructed a new sfsb: [email protected]3 
INFO: constructed a new view scoped bean: [email protected] 
INFO: destroying view scoped bean: [email protected] 
INFO: removing sfsb: [email protected]3 
INFO: destroying sfsb: [email protected]3 

INFO: constructed a new sfsb: [email protected]0 
INFO: constructed a new sfsb: [email protected]c 
INFO: constructed a new view scoped bean: [email protected] 
INFO: destroying view scoped bean: [email protected] 
INFO: removing sfsb: [email protected]c 
INFO: destroying sfsb: [email protected]c 

Und dann endlich, wenn ich die app entladen, beachten Sie die 10 überflüssig SFSBs schließlich zerstört werden; denn es basiert auf meinen Ruf

INFO: destroying sfsb: [email protected]9 
INFO: destroying sfsb: [email protected]9 
INFO: destroying sfsb: [email protected]7 
INFO: destroying sfsb: [email protected]e 
INFO: destroying sfsb: [email protected]0 
INFO: destroying sfsb: [email protected]b 
INFO: destroying sfsb: [email protected]8 
INFO: destroying sfsb: [email protected]0 
INFO: destroying sfsb: [email protected]5 
INFO: destroying sfsb: [email protected]0 

Nehmen Sie mein Wort, dass das Verhalten für 100 Treffer hält verursacht 200 Bohnen im gleichen Muster.

Antwort

0

Es ist kein Fehler, es ist eine Funktion. Und ein wichtiger. In Java EE erstellt der Container ein paar Instanzen verschiedener Dinge (z. B. zustandslose Beans, nachrichtengesteuerte Beans, Entitäten und sfbsbs) und puffert und chackt sie, und was nicht. Es ist einer der Gründe für die Verwendung von Java EE, den Container zu verlassen und damit umzugehen. Sie können dieses Verhalten in den meisten Containern konfigurieren.

Von der Glassfish-Dokumentation:

Darüber hinaus unterstützt die Glassfish Server eine Reihe von abstimmbaren Parameter, die auch die Anzahl der „Stateful“ Instanzen (Stateful Session Beans und Entity Beans) zwischengespeichert steuern als Dauer werden sie zwischengespeichert.

[..

]

Einer der wichtigsten Parameter für Glassfish Server Pooling ist steady-Pool-Größe. Wenn steady-pool-size auf einen Wert größer als 0 gesetzt ist, füllt der Container nicht nur den Bean-Pool mit der angegebenen Anzahl von Beans, sondern versucht auch sicherzustellen, dass diese Anzahl von Beans immer in der Datenbank verfügbar ist Freier Pool. Dies stellt sicher, dass genügend Beans im Bereitschaftszustand vorhanden sind, um Benutzeranforderungen zu bearbeiten.

(http://docs.oracle.com/cd/E18930_01/html/821-2418/beahn.html#beahq)

Wenn Sie dieses Verhalten nicht wünschen, können Sie es so konfigurieren, entfernt: Lesen und aus dem obigen Link entsprechende Links folgen.

+0

Ich denke nicht, dass das richtig ist. Ein beschränkter Cache (für Stateful Beans) unterscheidet sich von einem Pool (für Stateless Beans). Stateful Beans können nicht wiederverwendet werden. Das Verhalten, das ich sehe, ist 2 SFSB jedes Mal erstellt, wenn ich die Seite laden. Wenn ich die Seite 100 Mal lade, sehe ich 200 Beans erstellt. Die 100 "überflüssigen" Bohnen werden nie wieder verwendet; Es ist nicht so, als wären sie einem Pool hinzugefügt worden. Dies ist eindeutig kein wünschenswertes Verhalten. –

+0

Es ist wahr, dass sie nicht in der gleichen Weise oder aus dem gleichen Grund wie Staatenlose vereint sind. Sie werden jedoch in diesem Fall konstruiert (die Objektinitialisierung ist in Java "teuer"), um für eine zweite + gleichzeitige Notwendigkeit verfügbar zu sein. Wenn es wirklich wahr ist, dass 200 nach 100 Anfragen erstellt wird, haben wir wirklich ein Problem (mit der Standardkonfiguration von Glassfish). Es tut mir leid, aber ich bezweifle, dass das der Fall ist. – esej

+0

Re: "Zweifel" sehe meine Bearbeitung oben, einschließlich Protokolle –