JSF 页面元素无法从具有动作属性的支持 bean 触发方法。(JSF2.0 + primefaces)

Posted

技术标签:

【中文标题】JSF 页面元素无法从具有动作属性的支持 bean 触发方法。(JSF2.0 + primefaces)【英文标题】:JSF page element cannot trigger method from backing bean with action attribute.(JSF2.0 + primefaces) 【发布时间】:2011-08-09 08:50:39 【问题描述】:

我有一个带有 menuitem 元素的 primefaces 停靠导航栏,它应该会触发我的 Web 应用程序的注销机制,但它不起作用,我不知道为什么。有人可以帮我找出单击菜单项时未调用注销功能的原因吗?

这是 JSF 页面模板中的元素:

<h:form>
    <p:dock position="top">
    <p:menuitem value="Logout" icon="unsecuredimages/logout.png" action="securityController.logOut()" rendered ="#!securityController.checkLogged"/>

    </p:dock>   
</h:form>

这是logOut()方法所在的backing bean:

@ManagedBean
@RequestScoped
public class SecurityController 

...

public String logOut() 
        authentificationEJB.releaseUserState();     
        return "main.xhtml";
    

...

这是访问会话并从登录用户释放它的 EJB:

@Stateful(name = "ejbs/AuthentificationEJB")
public class AuthentificationEJB implements IAuthentificationEJB 
...
// Logout
    public void releaseUserState() 
        // 1-Check if there is something saved in the session(or wherever the
        // state is saved)
        if (!FacesContext.getCurrentInstance().getExternalContext()
                .getSessionMap().isEmpty()) 
            // 2-If 1 then flush it
            FacesContext.getCurrentInstance().release();
               
    
    ...
    

当我点击 menuItem 时,我得到了这个异常:

警告:StandardWrapperValve[Faces Servlet]:PWC1406:Servlet.service() 为 servlet Faces Servlet 抛出 例外 java.lang.IllegalStateException 在 com.sun.faces.context.FacesContextImpl.assertNotReleased(FacesContextImpl.java:639) 在 com.sun.faces.context.FacesContextImpl.getCurrentPhaseId(FacesContextImpl.java:515) 在 javax.faces.event.ExceptionQueuedEventContext.(ExceptionQueuedEventContext.java:148) 在 javax.faces.event.ExceptionQueuedEventContext.(ExceptionQueuedEventContext.java:101) 在 com.sun.faces.lifecycle.Phase.queueException(Phase.java:156) 在 com.sun.faces.lifecycle.Phase.queueException(Phase.java:149) 在 com.sun.faces.lifecycle.Phase.doPhase(Phase.java:109) 在 com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) 在 javax.faces.webapp.FacesServlet.service(FacesServlet.java:312) 在 org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215) 在 filters.RestrictPageFilter.doFilter(RestrictPageFilter.java:90) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215) 在 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:277) 在 org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188) 在 org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641) 在 com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97) 在 com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85) 在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185) 在 org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325) 在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226) 在 com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165) 在 com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791) 在 com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693) 在 com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954) 在 com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170) 在 com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135) 在 com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102) 在 com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88) 在 com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76) 在 com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53) 在 com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57) 在 com.sun.grizzly.ContextTask.run(ContextTask.java:69) 在 com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330) 在 com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309) 在 java.lang.Thread.run(Thread.java:662)

更新

<p:menuitem value="Logout" icon="unsecuredimages/logout.png" action="#securityController.logOut" rendered ="#!securityController.checkLogged"/>

@ManagedBean
@ViewScoped
public class SecurityController 

    @EJB
    private IAuthentificationEJB authentificationEJB;
    private String email;
    private String password;
    private String notificationValue;



    public String logOut() 
         HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
            if (session != null) 
                session.invalidate();
            
        return "main.xhtml";
    

    ...

【问题讨论】:

【参考方案1】:

我不知道你是否需要release() 方法。我认为这种方法是您异常的原因。来自javadoc的引用:

在 release() 被调用之后 FacesContext 实例(直到 FacesContext 实例已 通过实施回收 重用),调用任何其他方法 将导致 IllegalStateException 被扔掉。

...

实现必须调用 setCurrentInstance(javax.faces.context.FacesContext) 传递 null 以删除关联 在这个线程和这个死者之间 FacesContext 实例。

我使用以下注销方法。也许这对你有帮助:

public String logout() 
    HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
    if (session != null) 
        session.invalidate();
    
    user = null; // reset user
    // optional: addSuccessMessage

    return "login";

【讨论】:

我在托管 bean 上修改了我的代码(上面的更新)看起来像你的,现在我没有看到异常。我手动导航到其他页面,看起来会话正确无效。它工作正常,只是我没有重定向到 main.xhtml 为什么?【参考方案2】:

尝试从 RequestScoped 更改为例如 Sessions,我在使用 RequestScoped 支持 bean 的 apst 中遇到了一些麻烦。

【讨论】:

当我把 sessionScoped 我不能运行应用程序时,它说:org.glassfish.deployment.common.DeploymentException: WELD-000072 Managed bean declaring a passivating scope must be passivation capable. 当我使用 ViewScoped 时,我可以构建,但我有同样的例外。我还有什么其他选择?该托管 bean 不应该是 applicationScoped

以上是关于JSF 页面元素无法从具有动作属性的支持 bean 触发方法。(JSF2.0 + primefaces)的主要内容,如果未能解决你的问题,请参考以下文章

从支持 bean 访问 JSF 组件标记属性值

用户可以设置 JSF 支持 bean 中的哪些属性?

JSF 1.1-不刷新页面调用backing bean的动作方法(通过ajax/javascript)

JSF 如何从支持 bean 重定向到支持 bean 中动态构建的 URL?

如何在 JSF 页面加载之前在支持 bean 中启动特殊的 init 事件?

如何从 JSF 中的另一个 bean 获取 managedbean 属性