java.lang.IllegalStateException:CDATA标记可能无法嵌套

ali*_*noe 19 ajax jsf cdata primefaces illegalstateexception

我在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)
Run Code Online (Sandbox Code Playgroud)

我认为这是String对象的一些问题,因为当我对网站上显示的JPA实体属性进行硬编码时,一切都还可以.但是,当从数据库(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>
Run Code Online (Sandbox Code Playgroud)

Bal*_*usC 49

在呈现代码中的错误导致的JSF响应时抛出异常.但是,Mojarra无法使用内置的ajax异常处理程序正确处理此异常,导致您现在看到的另一个异常,隐藏了有关原始异常的所有详细信息.

仔细观察堆栈跟踪.从底部开始跟踪调用堆栈:

at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
Run Code Online (Sandbox Code Playgroud)

因此,它发生在渲染响应阶段.好的,看看下一行(上面一行):

at com.sun.faces.context.AjaxExceptionHandlerImpl.handle(AjaxExceptionHandlerImpl.java:123)
Run Code Online (Sandbox Code Playgroud)

嘿,它已经通过Mojarra的内置ajax异常处理程序 AjaxExceptionHandlerImpl!在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)
Run Code Online (Sandbox Code Playgroud)

因此,它试图将错误信息写入ajax响应.此信息必须放在CDATA块中.但是,启动CDATA块失败如下,因为显然已经打开了CDATA块:

java.lang.IllegalStateException: CDATA tags may not nest
Run Code Online (Sandbox Code Playgroud)

这反过来表明在编写ajax响应期间发生了异常,这很可能是因为您在getter方法中执行业务逻辑,该方法仅在生成HTML输出期间调用.所以这个过程最有可能如下:

  1. JSF进入RENDER_RESPONSE阶段.
  2. JSF需要生成HTML输出.
  3. 对于每个<f:ajax render="some">(或<p:ajax update="some">),它需要<update id="some">CDATA块内创建一个带有生成的HTML输出的XML (以保持XML输出在语法上有效).因此需要启动CDATA块.
  4. 在将HTML输出生成到CDATA块时,将评估所有渲染时EL表达式,包括value所有UI组件的属性.
  5. 某处,EL表达式后面的getter引发了一个由你自己的代码中的错误引起的异常.
  6. JSF迅速停止生成HTML输出,并没有关闭CDATA块.HTTP响应包含半烘焙数据.
  7. AjaxExceptionHandlerImpl 被触发了.
  8. AjaxExceptionHandlerImpl需要将异常/错误详细信息写入响应.但是,它没有检查响应是否已经写入.它盲目地试图打开一个CDATA块,因为它已经打开而失败了.它抛出了你所看到的异常,隐藏了它试图处理的真实底层异常的所有细节.

如您所见,问题是双重的:

  1. JSF渲染器不应该留下半熟的响应.
  2. Mojarra AjaxExceptionHandlerImpl应该检查/验证响应的状态.

如果您通过更换钻嘴鱼科的内置AJAX异常处理程序自定义的其立即打印堆栈跟踪,或由OmniFaces FullAjaxExceptionHandler它能够检测和清除halfbaked Ajax响应,那么它最终将揭示和展现真正的根本的错误在你的代码引起的.如前所述,它很可能是由getter方法中的业务逻辑引起的,这是一种不好的做法.