Jsf JavaEE6:数据库关闭时如何保护web应用程序
首先,我的框架是带有JSF、托管bean、EJB和JPA的JavaEE6。我写了一个简单的程序来查询数据库中的信息。所以,当我单击一个按钮时,它会触发一个事件到一个托管bean,其中一个事件侦听器方法将访问EJB方法。EJB方法将对实体执行一个简单的Jsf JavaEE6:数据库关闭时如何保护web应用程序,jsf,jpa,exception-handling,jakarta-ee,communicationexception,Jsf,Jpa,Exception Handling,Jakarta Ee,Communicationexception,首先,我的框架是带有JSF、托管bean、EJB和JPA的JavaEE6。我写了一个简单的程序来查询数据库中的信息。所以,当我单击一个按钮时,它会触发一个事件到一个托管bean,其中一个事件侦听器方法将访问EJB方法。EJB方法将对实体执行一个简单的select查询。如果在我选择之前或期间关闭数据库,则会出现异常 Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.ecl
select
查询。如果在我选择之前或期间关闭数据库,则会出现异常
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet successfully received from the server was 51,460 milliseconds ago. The last packet sent successfully to the server was 0 milliseconds ago.
Error Code: 0
我如何避免这种例外情况?肯定是一个尝试,捕捉,但不确定放在哪里。当我执行em.createNamedQuery
或em.remove
时,我试图捕获com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
,但我得到一个错误,错误是:Exception com.mysql.jdbc.exceptions.jdbc4.CommunicationsException从未在相应的try语句体中抛出
下面是我的代码,在哪里可以捕获异常
这是我的EJB
@Stateless
@LocalBean
public class DocumentSBean {
@PersistenceContext
private EntityManager em;
public List<User> listUser(){
Query query = em.createNamedQuery("User.listUser");
query.returnResultList();
}
}
编辑
我尝试了下面列出的两种方法,但仍然返回状态200,而不是firebug上的状态500
<p:commandButton update="myform" actionListener="#{document.setDisplayFacility}" rendered="#{utility.admin}" value="Facilities"/>
至少在我看来,数据库变得不可用是一个严重的错误,需要尽快处理。防止这种情况的一般方法是通过数据库集群强制实施高可用性和故障切换机制
但是,如果您没有此选项,也不希望用户看到一个大的胖异常,那么当发生此特定错误时,您可以尝试在一些用户友好的页面中路由他。为此,请将以下内容放入web.xml中(假设FacesServlet映射到*.faces):
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
/错误/error.faces
然后,在error.xhtml页面中,通常的方法是放置一些用户友好且基本上是道歉的消息,表明管理员对用户的不便感到多么抱歉
无论如何,通过捕获异常而不对其采取行动来处理这种情况,或者重新抛出异常,或者在可能的情况下在catch块中处理异常,通常被认为是在关键错误时的一种不好的做法,可能不会引起注意
关于你们的“从来并没有在相应的try语句的主体中抛出”的问题,你们可能想查看这篇文章
干杯 CommunicationsException封装在EclipseLink数据库异常中,这是一个运行时异常。如果您使用的是JPA或JTA,那么这也可能包装在PersistenceException或TransactionRolledbackException中。因此,请尝试捕获其中一个,或者最坏情况下的RuntimeException。通信异常将出现在由链引起的中
EclipseLink将自动尝试重新连接死连接,但如果数据库关闭,这将失败(您可能会看到错误记录3次),因此您需要向用户报告错误
我如何避免这种例外情况?绝对是一次尝试,在这里捕捉,但不确定放在哪里
只有在您能够以合理的方式处理异常的情况下才能捕获异常
我试图捕获com.mysql.jdbc.exceptions.jdbc4.CommunicationsException,但我得到了一个错误:Exception com.mysql.jdbc.exceptions.jdbc4.CommunicationsException从未在相应的try语句体中抛出
在本例中,通信异常
是数据库异常
的嵌套异常。EclipseLink已被掩盖,它已经捕获了通信异常
,并将其作为数据库异常
重新发布,而通信异常
是根本原因。比如:
try {
// Execute query.
} catch (Exception e) {
throw new DatabaseException("Internal Exception: " + e, e);
}
理论上,您只能按如下方式处理:
try {
// Let EclipseLink execute query.
} catch (DatabaseException e) {
if (e.getCause() instanceof CommunicationsException) {
// Handle.
}
}
然而,这是丑陋的,不建议在这种特殊情况下
下面是我的代码,在哪里可以捕获异常
取决于您希望如何处理异常。如果您想在一个通用错误页面中显示它,那么您不应该自己捕获它,而应该放手。然后servletcontainer将捕获并自行处理它。它将在web.xml
中查找最佳匹配的
,并显示它
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/generic-error.xhtml</location>
</error-page>
然而,尽管您的问题中没有明确指定,但根据您的问题历史,我知道您正在使用JSF。您需要记住,当ajax发出初始请求时,PrimeFaces不会显示错误页面。相反,它的ajax视图处理程序已经捕获了异常本身,它将委托给视图中的组件。尝试将ajax=“false”
添加到PrimeFaces命令组件中,您将最终看到显示servletcontainer的默认错误页面(如果在web.xml
中找到匹配的页面,则显示您的任何页面)
如果您想在PrimeFaces收到ajax错误时显示一些通用JSF UI,那么请使用
的错误方面。例如
<p:ajaxStatus>
<f:facet name="start"><h:graphicImage value="images/ajax-loader.gif" /></f:facet>
<f:facet name="success"><h:outputText value="" /></f:facet>
<f:facet name="error">
<h:panelGroup layout="block" styleClass="ui-message-error ui-widget ui-corner-all">
<h:outputText value="An error has occurred!" /><br />
<h:outputLink value="#" onclick="window.location.reload(true)"><h:outputText value="Please reload page and retry" /></h:outputLink><br />
<h:outputLink value="mailto:support@example.com?subject=Ajax%20Error"><h:outputText value="If in vain, please contact support" /></h:outputLink>
</h:panelGroup>
</f:facet>
</p:ajaxStatus>
(PrimeFaces 2.2 RC1中有一些导致错误面显示失败的错误面,它在PrimeFaces 2.1中正常工作)我已经更新了代码,请查看它们,因为我还有更多问题要问你。从上面的代码中,我将在哪里捕获PersistenceException
或transactionrolled backexception
。谢谢你,我觉得没用。我将您的代码放在我的web.xml
中。加载我的页面,关闭Mysql服务器,发出请求,它没有捕捉到正确的异常。换句话说,它没有将我重定向到我指定的错误页面。如果将CommunicationsException放在exception类型元素中,听起来很正常。这是因为当异常到达web层时,它很可能已被包装,因此不会被规则过滤(异常)
try {
// Execute query.
} catch (Exception e) {
throw new DatabaseException("Internal Exception: " + e, e);
}
try {
// Let EclipseLink execute query.
} catch (DatabaseException e) {
if (e.getCause() instanceof CommunicationsException) {
// Handle.
}
}
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/generic-error.xhtml</location>
</error-page>
<error-page>
<exception-type>org.eclipse.persistence.exceptions.DatabaseException</exception-type>
<location>/database-error.xhtml</location>
</error-page>
<p:ajaxStatus>
<f:facet name="start"><h:graphicImage value="images/ajax-loader.gif" /></f:facet>
<f:facet name="success"><h:outputText value="" /></f:facet>
<f:facet name="error">
<h:panelGroup layout="block" styleClass="ui-message-error ui-widget ui-corner-all">
<h:outputText value="An error has occurred!" /><br />
<h:outputLink value="#" onclick="window.location.reload(true)"><h:outputText value="Please reload page and retry" /></h:outputLink><br />
<h:outputLink value="mailto:support@example.com?subject=Ajax%20Error"><h:outputText value="If in vain, please contact support" /></h:outputLink>
</h:panelGroup>
</f:facet>
</p:ajaxStatus>