web-dev-qa-db-ja.com

java.lang.IllegalStateException:CDATAタグはネストできない

JSFページのajaxリクエストに問題があります。ボタンをクリックすると、次の例外が発生します。

SEVERE: Servlet.service() for servlet Faces Servlet threw exception
Java.lang.IllegalStateException: CDATA tags may not nest
    at com.Sun.faces.renderkit.html_basic.HtmlResponseWriter.startCDATA(HtmlResponseWriter.Java:630)
    at javax.faces.context.ResponseWriterWrapper.startCDATA(ResponseWriterWrapper.Java:172)
    at javax.faces.context.PartialResponseWriter.startError(PartialResponseWriter.Java:342)
    at org.primefaces.context.PrimePartialResponseWriter.startError(PrimePartialResponseWriter.Java:210)
    at com.Sun.faces.context.AjaxExceptionHandlerImpl.handlePartialResponseError(AjaxExceptionHandlerImpl.Java:200)
    at com.Sun.faces.context.AjaxExceptionHandlerImpl.handle(AjaxExceptionHandlerImpl.Java:123)
    at com.Sun.faces.lifecycle.Phase.doPhase(Phase.Java:119)
    at com.Sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.Java:139)

サイトに表示されているJPAエンティティプロパティをハードコーディングすると、すべてが問題ないので、Stringオブジェクトに問題があると思います。ただし、エンティティがデータベース(PostgreSQL)から取得されると、前述の例外がスローされます。

JSFコード:

<p:column>
    <f:facet name="header">
        Akcja
    </f:facet>
    <h:commandButton actionListener="#{mBDocumentMigration.actionEdit(object)}" value="Edytuj" rendered="#{mBDocumentMigration.editingObject == null}" >
        <f:ajax render="@form" execute="@form" />
    </h:commandButton>
    <h:commandButton action="#{mBDocumentMigration.actionZapisz}" value="Zapisz" rendered="#{mBDocumentMigration.editingObject != null}" >
    <f:ajax render="@form"  execute="@this" />
    </h:commandButton>
</p:column>
19
alinoe

コードのバグが原因でJSF応答のレンダリング中にスローされる例外があります。ただし、Mojarraは組み込みのajax例外ハンドラーでこの例外を適切に処理できなかったため、現在表示されている別の例外が発生し、元の例外に関するすべての詳細が隠されていました。

スタックトレースをよく見てください。呼び出しスタックを追跡するには、一番下から始めます。

at com.Sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.Java:139)

したがって、それはレンダリング応答フェーズ中に発生しました。さて、次の行(その上の行)を見てください。

at com.Sun.faces.context.AjaxExceptionHandlerImpl.handle(AjaxExceptionHandlerImpl.Java:123)

こんにちは、Mojarraの組み込みのAjax例外ハンドラーAjaxExceptionHandlerImplに渡されました!これはonlyであり、ajaxリクエスト中に例外が発生したときに呼び出されます。次の行を下から上に読んでください。

at com.Sun.faces.renderkit.html_basic.HtmlResponseWriter.startCDATA(HtmlResponseWriter.Java:630)
at javax.faces.context.ResponseWriterWrapper.startCDATA(ResponseWriterWrapper.Java:172)
at javax.faces.context.PartialResponseWriter.startError(PartialResponseWriter.Java:342)
at org.primefaces.context.PrimePartialResponseWriter.startError(PrimePartialResponseWriter.Java:210)
at com.Sun.faces.context.AjaxExceptionHandlerImpl.handlePartialResponseError(AjaxExceptionHandlerImpl.Java:200)

したがって、それはajax応答にエラー情報を書き込もうとしています。この情報はCDATAブロックに入れる必要があります。ただし、CDATAブロックが既に開いているため、CDATAブロックの開始は次のように失敗しました。

Java.lang.IllegalStateException: CDATA tags may not nest

これは、HTML出力の生成中にのみ呼び出されるゲッターメソッドでビジネスロジックを実行しているために、ajax応答の書き込み中に例外が発生したことを示しています。そのため、プロセスは次のようでした。

  1. JSFはRENDER_RESPONSEフェーズに入ります。
  2. JSFはHTML出力を生成する必要があります。
  3. すべての<f:ajax render="some">(または<p:ajax update="some">)について、生成されたHTML出力を CDATAブロック内に<update id="some"> XMLブロックを作成する必要があります (--- XML出力を構文的に有効に保つため)。したがって、CDATAブロックを開始する必要があります。
  4. HTML出力をCDATAブロックに生成している間、すべてのUIコンポーネントのvalue属性を含む、すべてのレンダリング時EL式が評価されます。
  5. どこかで、EL式の背後のゲッターが、独自のコードのバグが原因で例外をスローしました。
  6. JSFはHTML出力の生成を即座に停止し、CDATAブロックを閉じませんでした。 HTTP応答には、不完全なデータが含まれています。
  7. AjaxExceptionHandlerImplがトリガーされます。
  8. AjaxExceptionHandlerImplは、例外/エラーの詳細を応答に書き込む必要があります。ただし、応答がすでに記述されているかどうかは確認されませんでした。それは盲目的にCDATAブロックを開こうと試みますが、それはすでに開かれているために失敗しました。それはあなたが見ている例外を投げ、それが処理しようとした本当の根本的な例外に関するすべての詳細を隠しました。

ご覧のとおり、問題は2つあります。

  1. JSFレンダラーは応答を中途半端に残すべきではありませんでした。
  2. MojarraのAjaxExceptionHandlerImplは、応答の状態をチェック/確認する必要がありました。

Mojarraの組み込みajax例外ハンドラーを、スタックトレースをすぐに出力する カスタムハンドラー 、または OmniFaces FullAjaxExceptionHandlerに置き換えると、ハーフベイクされたajax応答 を検出およびクリーンアップすると、コードのバグによって引き起こされた実際の根本的な原因が最終的に明らかになり、表示されます。前に述べたように、それはおそらくゲッターメソッドでビジネスロジックを 実行することによって引き起こされますが、これは悪い習慣です

49
BalusC

私はあなたと同じ問題を抱えていました、バッキングBeanからのオートコンプリートコンポーネントとのバインディングを使用したとき、それはうまくいきました。

<p:autoComplete id="autocomplete" binding="#{searchBean.compui}" title="Find" value="#{searchBean.searchfor}" forceSelection="false" queryDelay="30" dropdown="true" maxResults="20" emptyMessage="None" completeMethod="#{searchBean.complete}" style="width: 90%;"/>
<p:commandButton id="cmdsearch" value="#{msg.search}" action="#{searchBean.search}" update="tblprocresults" icon="ui-icon-zoomin"/>

バッキングビーンズで

private AutoComplete compui;
//compui is initialized when bean is constructed
    public AutoComplete getCompui() {
            return compui;
        }

        public void setCompui(AutoComplete compui) {
            this.compui = compui;
        }
0
MTom