首先,我的框架是带有JSF,托管bean,EJB和JPA的Java EE 6。我编写了一个简单的程序来查询数据库中的信息。因此,当我单击一个按钮时,它将触发一个事件到托管bean,事件侦听器方法将在其中访问EJB方法。 EJB方法将对实体执行简单的select
查询。如果在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
我如何避免这种异常?这里绝对是
try, catch
,但不确定将其放置在何处。当我执行em.createNamedQuery
或em.remove
时,我尝试捕获com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
,但出现错误消息:Exception com.mysql.jdbc.exceptions.jdbc4.CommunicationsException is never thrown in body of corresponding try statement
。以下是我的代码,在哪里可以捕获到异常?
这是我的
EJB
@Stateless
@LocalBean
public class DocumentSBean {
@PersistenceContext
private EntityManager em;
public List<User> listUser(){
Query query = em.createNamedQuery("User.listUser");
query.returnResultList();
}
}
这是我的
ManagedBean
@ManagedBean(name="document")
@ViewScoped
public class DisplayListController implements Serializable {
@EJB
DocumentSBean sBean;
List<User> users = null;
public void foo(){
users = sBean.listUser();
}
}
编辑
我尝试下面列出的两种方法,但是在萤火虫上仍返回状态200而不是500
<p:commandButton update="myform" actionListener="#{document.setDisplayFacility}" rendered="#{utility.admin}" value="Facilities"/>
要么
<p:commandButton update="myform" actionListener="#{document.setDisplayFacility}" rendered="#{utility.admin}" value="Facilities">
<p:ajax actionListener="#{document.setDisplayFacility}" update="myform" event="click"/>
</p:commandButton>
这是setDisplayFacility()
public void setDisplayFacility(){
facilities = sBean.getAllFacilities(); //sBean is EJB
displayFacility = true;
}
最佳答案
我如何避免这种异常?绝对可以尝试,抓住这里,但不确定将其放在何处。
仅在可以合理处理的地方捕获异常。
我尝试捕获com.mysql.jdbc.exceptions.jdbc4.CommunicationsException,但我收到一个错误消息:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException异常从未抛出在相应的try语句的主体中。
在这种情况下,CommunicationsException
是DatabaseException
的嵌套异常。 EclipseLink已经被掩盖在已经捕捉到CommunicationsException
并将其作为DatabaseException
并以CommunicationsException
为根本原因的情况下被抛出。就像是:
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.
}
}
但是,这很丑陋,在这种情况下不建议使用。
以下是我的代码,在哪里可以捕获到异常?
取决于您要如何处理异常。如果要在一般错误页面上显示它,那么您不应该自己抓住它,而应该放手去做。然后,servlet容器将自己捕获并处理它。它将在
<error-page>
中查找最匹配的web.xml
并显示它。<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/generic-error.xhtml</location>
</error-page>
这将为
/generic-error.xhtml
的所有子类显示java.lang.Exception
。如果要在特定的错误页面中显示它,则需要声明更具体的
<exception-type>
以匹配实际的异常类型。例如。:<error-page>
<exception-type>org.eclipse.persistence.exceptions.DatabaseException</exception-type>
<location>/database-error.xhtml</location>
</error-page>
但是,尽管您的问题中未明确指定,但根据您的问题历史记录,我知道您正在将JSF与PrimeFaces一起使用。您需要记住,当ajax发出初始请求时,PrimeFaces不会显示错误页面。相反,它的ajax视图处理程序本身已经捕获了异常,它将委派给视图中的
<p:ajaxStatus>
组件。尝试将ajax="false"
添加到PrimeFaces命令组件中,您最终将看到显示servlet容器的默认错误页面(如果在web.xml
中找到匹配的错误页面,则显示任何错误页面)。如果要在PrimeFaces收到Ajax错误时显示一些通用JSF UI,请使用
error
的<p:ajaxStatus>
构面。例如。<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:[email protected]?subject=Ajax%20Error"><h:outputText value="If in vain, please contact support" /></h:outputLink>
</h:panelGroup>
</f:facet>
</p:ajaxStatus>
(但是,PrimeFaces 2.2 RC1中存在一些bug导致显示错误构面失败,因此在PrimeFaces 2.1中可以正常工作)