2012-06-06 42 views
2

我使用JBoss6.1.Final,JSF 2.0(鑽嘴魚科),虛焊CDI,MyFaces的CODI 1.0.5(用於視圖的訪問範圍的)SFSB被移除

我使用類似的網關從Real World Java EE Patterns Rethinking Best Practices模式(不幸的是,我沒有與我在一起,所以我可能已經搞砸了這裏的東西)。基本上,應用程序允許用戶進入「編輯模式」並使用擴展的持久化上下文來編輯維護在@ViewAccessScoped支持bean中的人員列表(創建,編輯,刪除),然後單擊「保存」命令鏈接進行刷新他們對數據庫的所有更改。起初,我遇到了ViewExpiredExceptions問題(如果瀏覽器空閒超過會話超時期,然後再執行進一步的請求),但我添加了一些jQuery來向一個使會話保持活動狀態的servlet發出get請求(稱爲10會話超時前的秒數)。這似乎是工作,但現在我有另一個問題,支持bean也是一個SFSB,並在一段空閒時間後,它被刪除,導致在我嘗試執行時記錄以下錯誤消息(和所有ajax呈現的數據消失)更多編輯...

13:06:22,063 SEVERE [javax.enterprise.resource.webcontainer.jsf.context] javax.el.E​​LException:/index.xhtml @ 27,81 rendered =「#{!conversationBean。編輯模式}「:javax.ejb.NoSuchEJBException:無法找到有狀態的bean:43h1h2f-9c7qkb-h34t0f34-1 -h34teo9p-de

有關如何防止SFSB移除或至少更好地處理它的任何想法?

這裏是我的支持bean:

package com.ray.named; 

import java.io.Serializable; 
import java.util.List; 

import javax.annotation.PostConstruct; 
import javax.ejb.EJBTransactionRolledbackException; 
import javax.ejb.Stateful; 
import javax.ejb.TransactionAttribute; 
import javax.inject.Named; 
import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 
import javax.persistence.PersistenceContextType; 

import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.ViewAccessScoped; 

import com.ray.model.Person; 

@Named 
@Stateful 
@ViewAccessScoped 
@TransactionAttribute(javax.ejb.TransactionAttributeType.NEVER) 
public class ConversationBean implements Serializable { 
    private static final long serialVersionUID = 1L; 
    //properties 
    private List<Person> people; 
    private String name; 
    private Boolean editMode; 

    @PersistenceContext(type=PersistenceContextType.EXTENDED) 
    private EntityManager em; 

    @PostConstruct 
    public void init() { 
    people = em.createNamedQuery("Person.findAll", Person.class).getResultList(); 
    setEditMode(false); 
    } 

    //event listeners 
    public void beginEdits() { 
    setEditMode(true); 
    } 

    public void addPerson() { 
    Person p = new Person(name); 
    em.persist(p); 
    people.add(p); 
    name = null; 
    } 

    public void removePerson(Person p) { 
    people.remove(people.indexOf(p)); 
    em.remove(p); 
    } 

    //this method flushes the persistence context to the database 
    @TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW) 
    public void saveEdits() { 
    setEditMode(false); 
    } 

    //getters/setters 
    public List<Person> getPeople() { 
    return people; 
    } 

    public String getName() { 
    return name; 
    } 

    public void setName(String name) { 
    this.name = name; 
    } 

    public Boolean getEditMode() { 
    return editMode; 
    } 

    public void setEditMode(Boolean editMode) { 
    this.editMode = editMode; 
    } 
} 

這裏的人實體bean:

package com.ray.model; 

import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.NamedQueries; 
import javax.persistence.NamedQuery; 
import javax.persistence.Version; 

@Entity 
@NamedQueries({ 
    @NamedQuery(name="Person.findAll", 
       query="SELECT p FROM Person p") 
}) 
public class Person { 
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Integer id; 
    private String name; 
    @Version 
    private int version; 

    public Person() { } 

    public Person(String name) { 
    setName(name); 
    } 

    public boolean equals(Object o) { 
    if (!(o instanceof Person)) { 
     return false; 
    } 
    return id == ((Person)o).id; 
    } 

    //getters/setters 
    public String getName() { 
    return name; 
    } 
    public void setName(String name) { 
    this.name = name; 
    } 

    public Integer getId() { 
    return id; 
    } 

    public int getVersion() { 
    return version; 
    } 

    public void setVersion(int version) { 
    this.version = version; 
    } 
} 

這裏的觀點:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" 
     xmlns:h="http://java.sun.com/jsf/html" 
     xmlns:f="http://java.sun.com/jsf/core" 
     xmlns:ui="http://java.sun.com/jsf/facelets"> 
<h:head> 
    <script src="http://code.jquery.com/jquery-latest.min.js"></script> 
    <script> 
    $(document).ready(function() { 
    setInterval(function() { 
     $.get("#{request.contextPath}/poll"); 
    }, #{(session.maxInactiveInterval - 10) * 1000}); 
    }); 
    </script> 
    <title>Conversation Test</title> 
</h:head> 
<h:body> 
    <h:form> 
    <h:commandLink value="Begin Edits" rendered="#{!conversationBean.editMode}"> 
     <f:ajax render="@form" listener="#{conversationBean.beginEdits}"/> 
    </h:commandLink> 
    <h:commandLink value="Save" rendered="#{conversationBean.editMode}"> 
     <f:ajax render="@form" listener="#{conversationBean.saveEdits}"/> 
    </h:commandLink> 
    <h:dataTable id="peopleTable" value="#{conversationBean.people}" var="person"> 
     <h:column> 
     <f:facet name="header">Name</f:facet> 
     <h:panelGroup> 
      <h:inputText value="#{person.name}" disabled="#{!conversationBean.editMode}"> 
      <f:ajax/> 
      </h:inputText> 
      <h:commandLink value="X" disabled="#{!conversationBean.editMode}"> 
      <f:ajax render="@form" listener="#{conversationBean.removePerson(person)}"/> 
      </h:commandLink> 
     </h:panelGroup> 
     </h:column> 
    </h:dataTable> 
    <h:panelGrid columns="2"> 
     <h:outputLabel for="name">Name:</h:outputLabel> 
     <h:inputText id="name" value="#{conversationBean.name}" disabled="#{!conversationBean.editMode}"/> 
    </h:panelGrid> 
    <h:commandButton value="Add" disabled="#{!conversationBean.editMode}"> 
     <f:ajax execute="@form" render="@form" listener="#{conversationBean.addPerson}"/> 
    </h:commandButton> 
    </h:form> 
</h:body> 
</html> 

這裏是用來保持會話處於活動一個servlet(在會話過期前10秒由jQuery ajax調用請求):

package com.ray.web; 

import java.io.IOException; 

import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

public class PollServlet extends HttpServlet { 
    private static final long serialVersionUID = 1L; 

    public void init() throws ServletException { 
    } 

    public String getServletInfo() { 
    return null; 
    } 

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { 
    request.getSession(); //Keep session alive 
    } 

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { 
    } 

    public void destroy() { 
    } 
} 

回答

1

我如何能防止SFSB去除或至少更加妥善地處理它 任何想法?

進一步調查,我建議採取看看EJB的生命週期掛鉤鈍化,並添加一些調試輸出那裏。

如果這是問題的根源,您將能夠配置/停用鈍化 - 但可擴展性可能會成爲問題。

老實說,這種情況對我來說似乎很少見。一般來說,我希望請求/會話/會話在默認邊界內或多或少地工作 - 如果您發現自己編寫的代碼繞過了這種情況,那麼您可以使用RESTful /無狀態方法來更好地工作......?

如果有更多信息,請更新問題。

+0

感謝又一次月只是好奇,你看到什麼硬傷與我的示例代碼?有什麼你會做不同的事情嗎? – JasonI

+0

我添加了@PrePassivate批註的方法,可以看到backing/session bean確實被鈍化了。我正在試驗RichFaces a4j:poll,它的session時間比session.maxInactiveInterval小10秒,這似乎是在做伎倆。只要瀏覽器窗口打開,會話就保持活動狀態。 – JasonI

+0

@Jasonl(#1)不,你的代碼沒有問題。我不能表達自己,因爲我已經在答案中做了... –