2

まず、私のフレームワークは、JSF、マネージドBean、EJB、およびJPAを備えたJavaEE6です。データベースから情報を照会する簡単なプログラムを作成します。したがって、ボタンをクリックすると、マネージドBeanへのイベントがトリガーされ、イベントリスナーメソッドがEJBメソッドにアクセスします。EJBメソッドはselect、エンティティに対して単純なクエリを実行します。Iの前またはその間にデータベースがシャットダウンされた場合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();
   }
}

編集

以下にリストされているように両方の方法を試しますが、firebugで500ではなく200のステータスを返します

<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;
}
4

3 に答える 3

6

この例外からどのように保護しますか?間違いなく試してみてください。ここでキャッチしてください。ただし、どこに配置するかはわかりません。

合理的な方法で処理できる場合にのみ、例外をキャッチしてください。


com.mysql.jdbc.exceptions.jdbc4.CommunicationsExceptionをキャッチしようとしましたが、次のようなエラーが発生しました。例外com.mysql.jdbc.exceptions.jdbc4.CommunicationsExceptionが対応するtryステートメントの本文にスローされることはありません。

このCommunicationsException場合、はネストされた例外ですDatabaseException。EclipseLinkは、根本的な原因と同様に、すでにそれをキャッチしてCommunicationsException再スローしています。何かのようなもの:DatabaseExceptionCommunicationsException

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はそれ自体をキャッチして処理します。で最も一致するものを検索して<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>

ただし、質問で明示的に指定されていませんが、質問履歴に基づいて、PrimeFacesでJSFを使用していることがわかります。最初のリクエストがajaxによって行われた場合、PrimeFacesはエラーページを表示しないことに注意する必要があります。代わりに、そのajaxビューハンドラーはすでに例外自体をキャッチしており<p:ajaxStatus>、ビュー内のコンポーネントに委任します。PrimeFacesコマンドコンポーネントに追加ajax="false"してみてください。最終的に、servletcontainerのデフォルトのエラーページが表示されます(または、一致するものweb.xmlが見つかった場合は、任意のページが表示されます)。

PrimeFacesがajaxエラーを受け取ったときに一般的なJSFUIを表示する場合は、の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: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では正しく機能します)

于 2010-11-16T19:58:38.977 に答える
2

少なくとも私の見解では、データベースが使用できなくなることは重大なエラーであり、通常はできるだけ早く処理する必要があります。このような状況から保護するための一般的なアプローチは、データベースのクラスタリングを通じて高可用性とフェイルオーバーのメカニズムを適用することです。

ただし、このオプションがない場合や、ユーザーに大きな例外を表示させたくない場合は、この特定のエラーが発生したときに、ユーザーフレンドリーなページにユーザーをルーティングすることをお勧めします。これを行うには、web.xmlに次のように記述します(FacesServletが* .facesにマップされていると仮定します)。

<error-page>
    <exception-type>com.mysql.jdbc.exceptions.jdbc4.CommunicationsException</exception-type>
    <location>/errors/error.faces</location>
</error-page>

次に、error.xhtmlページに、一般的なアプローチは、管理者がユーザーの不便をどれほど残念に思っているかを示す、ユーザーフレンドリーで大部分が謝罪のメッセージを入れることです...

いずれにせよ、例外をキャッチし、それらに対処せずに、それらを再スローするか、キャッチブロックで処理することによって、そのような状況に対処することは、一般に、重大なエラーが気付かれない可能性がある場合の悪い習慣と見なされます。 。

「対応するtryステートメントの本文にスローされることはありません」という質問については、この記事を確認することをお勧めします。

乾杯!

于 2010-11-10T17:05:20.980 に答える
2

CommunicationsExceptionは、ランタイム例外であるEclipseLinkDatabaseExceptionにラップされます。JPAまたはJTAを使用している場合、これもPersistenceExceptionまたはTransactionRolledbackExceptionにラップされる可能性があります。したがって、これらの1つ、または最悪の場合のRuntimeExceptionをキャッチしてみてください。CommunicationsExceptionは、チェーンによって引き起こされます。

EclipseLinkは自動的に切断された接続の再接続を試みますが、データベースがダウンしている場合、これは失敗するため(エラーが3回ログに記録される場合があります)、ユーザーにエラーを報告する必要があります。

于 2010-11-11T13:45:02.197 に答える