2012-05-03 54 views
3

我試着用EJB Session Beans做一個例子。我想看看他們之間的差異。我的基本項目圖如下;@Stateless Session Bean充當@Singleton Bean

http://img109.imageshack.us/img109/8262/85220418.png

項目就像是一個購物車。當我通過注入的EJB調用託管bean以獲取添加的Urun對象的結果時,結果列表必須是最後一個Urun對象。導致我的EJB是@Stateless bean。但是,當我運行該應用程序時,它會保留所有新添加的Urun對象。但它是無狀態的,它必須在每個動作中保留最後一個Urun對象。然後,當我在其他Web瀏覽器中打開應用程序頁面時,它會列出添加Urun對象之前的列表。但是在我的模型中託管bean和Ejb是無狀態的。但它是一個Singleton bean。我的問題在哪裏?

@Stateless 
public class AlisverisSepetiEJB { 

    List<Urun> urunler=new ArrayList<>(); 

    public List<Urun> getUrunler() { 
     return urunler; 
    } 

    public void setUrunler(List<Urun> urunler) { 
     this.urunler = urunler; 
    } 

    public void urunEkle(Urun urun){ 
     urunler.add(urun); 
    } 

} 

@ManagedBean(name="bean") 
@RequestScoped 
public class JSFYonetimliNesne { 

    public JSFYonetimliNesne(){ 
     System.out.println("Yönetimli nesne çalıştı"); 
    } 

    @EJB 
    AlisverisSepetiEJB alisverisSepeti; 

    Urun urun=new Urun(); 
    List<Urun> urunler; 


    public List<Urun> getUrunler() { 
     return alisverisSepeti.getUrunler(); 
    } 

    public void setUrunler(List<Urun> urunler) { 
     this.urunler = urunler; 
    } 

    public Urun getUrun() { 
     return urun; 
    } 

    public void setUrun(Urun urun) { 
     this.urun = urun; 
    } 

    public void sepeteKoy(){ 
     alisverisSepeti.urunEkle(urun); 
     urun=new Urun(); 
    } 

} 

public class Urun { 

    String urunAdi; 
    Long fiyat; 
    Long gramaj; 

    public Long getFiyat() { 
     return fiyat; 
    } 

    public void setFiyat(Long fiyat) { 
     this.fiyat = fiyat; 
    } 

    public Long getGramaj() { 
     return gramaj; 
    } 

    public void setGramaj(Long gramaj) { 
     this.gramaj = gramaj; 
    } 

    public String getUrunAdi() { 
     return urunAdi; 
    } 

    public void setUrunAdi(String urunAdi) { 
     this.urunAdi = urunAdi; 
    } 

} 

<?xml version="1.0" encoding="UTF-8"?> 

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml" 
     xmlns:h="http://java.sun.com/jsf/html" 
     xmlns:f="http://java.sun.com/jsf/core"> 
    <h:head> 
     <title>Alışveriş Sepeti</title> 
    </h:head> 
    <h:body> 
     Alışveriş Sepeti 
     <h:form> 

      <h:panelGrid columns="2"> 
      <h:outputLabel value="Ürün adı : "/> 
      <h:inputText value="#{bean.urun.urunAdi}"/> 
      <h:outputLabel value="Ürün fiyatı : "/> 
      <h:inputText value="#{bean.urun.fiyat}"/> 
      <h:outputLabel value="ÜRün gramajı : "/> 
      <h:inputText value="#{bean.urun.gramaj}"/> 
      </h:panelGrid> 

      <h:commandButton action="#{bean.sepeteKoy}" value="Sepete Ekle"/> 

      <br><h:outputLabel value="Sepetteki Ürünler"/></br> 


      <h:dataTable value="#{bean.urunler}" var="item" border="1"> 

      <h:column > 
       <f:facet name="header"> 
        <h:outputLabel value="Ürün adı"/> 
       </f:facet> 
      <h:outputText value="#{item.urunAdi}"/> 
      </h:column> 

      <h:column > 
       <f:facet name="header"> 
        <h:outputLabel value="Ürün fiyatı"/> 
       </f:facet> 
      <h:outputText value="#{item.fiyat}"/> 
      </h:column> 

      <h:column > 
       <f:facet name="header"> 
        <h:outputLabel value="Ürün gramajı"/> 
       </f:facet> 
      <h:outputText value="#{item.gramaj}"/> 
      </h:column> 

      </h:dataTable> 

     </h:form> 

    </h:body> 
</html> 
+2

在SO上發佈時,請不要發佈本地化的源代碼。 –

回答

5

這很可能是的AlisverisSepetiEJB相同的實例被調用共享(容器可以做到這一點,這是完全合法的) 。正是因爲EJB的@Stateless的無狀態性質,您應該在而不是中聲明實例屬性!

刪除List<Urun> urunler = new ArrayList<>();聲明和所有關聯的方法,將無狀態bean看作一個類,其所有方法都是靜態的 - 意味着它們不能使用任何實例屬性,並且必須完全獨立於實例數據;如果需要在調用之間維護任何狀態,那麼它必須作爲參數從EJB調用點傳遞。在@Stateless EJB中允許的唯一實例變量是本身無狀態和/或不可變的屬性。

如果您需要在調用之間維護購物車的狀態,則必須將其保存在有狀態上下文中的其他地方(例如,Web應用程序的Session上下文)或將EJB標記爲@Stateful

+2

同意。如果你在@Stateless bean中有一些成員變量,它應該只是一個EntityManager,它不包含任何「狀態」信息。 – toto2

+1

無狀態bean可能包含各種狀態,用戶可觀察狀態除外。所以一個實體管理者,也許是一個連接到某個東西等都是好的,只要它們在內部用作緩存或性能優化。 –

相關問題