Java 处理';EJB不存在';或';无法从备份存储加载密钥';

Java 处理';EJB不存在';或';无法从备份存储加载密钥';,java,jsf,exception,jakarta-ee,ejb,Java,Jsf,Exception,Jakarta Ee,Ejb,所以问题很简单: 我们正在使用JSF2.0和Primefaces以及EJB来处理我们的应用程序,我们遇到了一个问题。我们有一个@SessionScopedbean,其中存储了所有的@有状态会话bean 在一种情况下,(当我们没有处理来自JPA的一些异常时),存在一个异常: javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.v20110

所以问题很简单:

我们正在使用JSF2.0和Primefaces以及EJB来处理我们的应用程序,我们遇到了一个问题。我们有一个
@SessionScoped
bean,其中存储了所有的
@有状态会话bean

在一种情况下,(当我们没有处理来自JPA的一些异常时),存在一个异常:

javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "webuser_idwebuser_pk"
  Detail: Key (idwebuser)=(6) already exists.
它会导致破坏我们的一个有状态会话Bean。 因此,在刷新网站之后,当JSF仍然正常工作时,在填写表单并尝试提交表单之后,通过调用该Bean中的方法,出现了一个异常:

javax.ejb.NoSuchObjectLocalException: The EJB does not exist. session-key: 22900a4d007e1f-6dcc714a-0
问题最大的是,我们必须重新启动并重新部署应用程序,使其在同一台计算机(或web浏览器)上工作,因为JSF的
@SessionScoped
Bean是通过cookie或其他方式保存的

因此,我想解决办法是强制破坏
@SessionScoped
或以某种方式刷新会话,但实际上我不知道如何做到这一点。 或者什么是更好的方法


谢谢

要解决这个问题,您需要了解EJB中应用程序异常和系统异常之间的区别

这些异常大致分别对应于检查异常和运行时异常

应用程序异常应该由您自己的代码处理,并且不会导致事务回滚或bean的破坏。系统异常具有相反的效果,将导致回滚和EJB bean的破坏

后一种效果就是你所看到的。JPA抛出未检查的异常,从而成为系统异常,从而导致SFSB被销毁。JSF和CDI管理的bean都参与了这个“系统异常”事件,因此它们只会传播异常并保持活动状态


您可能需要定义一个新的异常,用@ApplicationException注释该异常,然后将其回滚属性设置为true。捕获SFSB中的JPA异常,并使用自定义异常对其进行包装和重播

好的,我自己找到了答案。 实际上,我需要的是通过扩展ActionListenerImpl来处理JSF视图中的异常

原文如下:

但我所做的是通过使HTTP会话无效来扩展异常处理,最终结束了
@SessionScoped
托管Bean的生命,并导致重新注入SSB。像这样:

private void gotoErrorPage(MethodExpression expression) {
        FacesContext context = FacesContext.getCurrentInstance();
        Application application = context.getApplication();

        HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
        if (session != null) {
            session.invalidate();
        }

        NavigationHandler navHandler = application.getNavigationHandler();
        navHandler.handleNavigation(context, null == expression ? null : expression.getExpressionString(), NAV_ERRORPAGE);
        context.renderResponse();
    }

我想我这里也有类似的问题(对不起,没有答案)。哪种是您的设置?为每个小JPA异常使HTTP会话无效是一个非常糟糕的解决方案。这将是一个巨大的开销,并导致每个视图都会无缘无故地过期。我们处理其他异常,但这会处理我们没有预测到的异常。如果您执行“捕获所有”(捕获异常,或者如果您真的非常绝望,甚至可以丢弃),那么将不会出现任何不可预测的异常。JPA都有文档记录(参见各自的JavaDocs),因此很难称之为意外/不可预测。但嘿,这是你的密码!只是警告其他人不要盲目遵循您的解决方案;)我没有说“这”是盲目的,但用户不应该盲目地遵循它。如果你真的认为这是一个很好的解决方案,那么我很抱歉。我无意冒犯你或任何人,但事实上你没有看到它表明你的理解或总体洞察力有问题。充其量,你的解决方案是一个快速的黑客,在短时间内设置到位。最糟糕的情况是,这是一场绝望的苦战,因为你没有抓住根本原因。这绝对不是一个“真正好的解决方案”。对不起…你为什么觉得我被冒犯了。我只是想知道,处理用户在长期使用应用程序时可能遇到的异常的更好方法是什么,因为通常不可能预测每个异常。由于其中一些异常可能会影响要处理的EJB bean,我们需要使用户的会话无效。那么我们应该如何处理呢?我只是有点好奇,因为你给出的解决方案不是很清楚,表明你可以预测每一种情况。