ajax java.lang.IllegalStateException:CDATA 标签不能嵌套

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11901882/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 10:48:50  来源:igfitidea点击:

java.lang.IllegalStateException: CDATA tags may not nest

ajaxjsfprimefacescdataillegalstateexception

提问by alinoe

I've got a problem with an ajax request in a JSF page. When I click on the button, I get this exception:

我在 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)

I think it's some problem with Stringobjects, because when I hardcode the JPA entity properties which are shown on the site, then everything is OK. However when the entity is retrieved from the database (PostgreSQL), it throws the aforementioned exception.

我认为这是String对象的一些问题,因为当我对站点上显示的 JPA 实体属性进行硬编码时,一切正常。但是,当从数据库 (PostgreSQL) 检索实体时,它会引发上述异常。

JSF code:

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>

回答by BalusC

There's an exception being thrown during rendering the JSF response caused by a bug in your code. However, Mojarra in turn failed to properly handle this exception with the builtin ajax exception handler, causing another exception which you're now seeing, hiding away all detail about the original exception.

在呈现由代码中的错误引起的 JSF 响应期间抛出异常。但是,Mojarra 反过来又无法使用内置的 ajax 异常处理程序正确处理此异常,从而导致您现在看到的另一个异常,隐藏了有关原始异常的所有详细信息。

Look closer at the stack trace. Start at the bottom to track the call stack:

仔细查看堆栈跟踪。从底部开始跟踪调用堆栈:

at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)

Thus, it happened during render response phase. Okay, look at the next line (the one above it):

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

at com.sun.faces.context.AjaxExceptionHandlerImpl.handle(AjaxExceptionHandlerImpl.java:123)

Hey, it's been passed through Mojarra's builtin ajax exception handler AjaxExceptionHandlerImpl! This is onlyinvoked when an exception has occurred during an ajax request. Okay, read the next lines further from bottom to top:

嘿,它已经通过了 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)

It's thus attempting to write the error information to the ajax response. This information has to go in a CDATA block. However, starting a CDATA block failed as follows because there's apparently already a CDATA block open:

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

java.lang.IllegalStateException: CDATA tags may not nest

This in turn indicates that the exception occurred during writing the ajax response, most likely because you're performing business logic in a getter method which is only invoked during generating the HTML output. So the process was most likely as follows:

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

  1. JSF enters RENDER_RESPONSE phase.
  2. JSF needs to generate HTML output.
  3. For every <f:ajax render="some">(or <p:ajax update="some">), it needs to create a <update id="some">XML block with the generated HTML output inside a CDATA block(to keep the XML output syntactically valid). So a CDATA block needs to be started.
  4. While generating the HTML output into a CDATA block, all render-time EL expressions are evaluated, including valueattribute of all UI components.
  5. Somewhere, the getter behind the EL expression threw an exception caused by a bug in your own code.
  6. JSF promptly stopped generating HTML output and didn't close the CDATA block. The HTTP response contains halfbaked data.
  7. AjaxExceptionHandlerImplis triggered.
  8. AjaxExceptionHandlerImplneeds to write the exception/error detail to the response. However, it didn't check if the response is already written. It blindly attempts to open a CDATA block which in turn failed because it's already opened. It threw the exception you're seeing, hiding away all detail about the real underlying exception it tried to handle.
  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 块,而该块又失败了,因为它已经打开了。它抛出了你看到的异常,隐藏了它试图处理的真正底层异常的所有细节。

As you can see, the problem is two-fold:

如您所见,问题有两个方面:

  1. JSF renderer should not have left the response halfbaked.
  2. Mojarra's AjaxExceptionHandlerImplshould have checked/verified the state of the response.
  1. JSF 渲染器不应该让响应半途而废。
  2. MojarraAjaxExceptionHandlerImpl应该检查/验证响应的状态。

If you replace Mojarra's builtin ajax exception handler by a custom one which immediately prints the stack trace, or by OmniFaces FullAjaxExceptionHandlerwhich is capable of detecting and cleaning halfbaked ajax responses, then it will finally reveal and show the real underlying caused by a bug in your code. As said before, it's most likely caused by performing business logic in a getter method, which is a bad practice.

如果您将 Mojarra 的内置 ajax 异常处理程序替换为立即打印堆栈跟踪自定义异常处理程序,或者替换FullAjaxExceptionHandler为能够检测和清理半生不熟的 ajax 响应的 OmniFaces,那么它将最终揭示并显示由代码中的错误引起的真正底层. 如前所述,这很可能是由在 getter 方法中执行业务逻辑引起的,这是一种不好的做法

回答by MTom

I had the same problem as yours, When I used binding with autocomplete component from the backing bean it worked fine.

我遇到了和你一样的问题,当我使用来自支持 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"/>

and in the backing bean

并在支持 bean 中

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

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

回答by REDA

CDATA issue is not a PrimeFaces question but related to JSF implementation who is responsible of providing the partial output. replace by it's JSF property ;)

CDATA 问题不是 PrimeFaces 问题,而是与负责提供部分输出的 JSF 实现有关。替换为它的 JSF 属性;)

回答by Karl Richter

If you also see java.lang.ClassCastException: com.sun.faces.facelets.compiler.UIInstructions cannot be cast to org.primefaces.component.tree.UITreeNodein the server log, add

如果您还在java.lang.ClassCastException: com.sun.faces.facelets.compiler.UIInstructions cannot be cast to org.primefaces.component.tree.UITreeNode服务器日志中看到,请添加

<context-param>
  <param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
  <param-value>true</param-value>
</context-param>

to /WEB-INF/web.xml

/WEB-INF/web.xml

回答by Eagle's Nest

Just to throw in something to consider as well, sometimes it can be a really bone-headed error.

只是为了考虑一些事情,有时它可能是一个非常愚蠢的错误。

For example, sometimes I would get this same error message if I forgot to initialize an ArrayList in one of my beans that the xhtml page is using:

例如,如果我忘记在 xhtml 页面使用的其中一个 bean 中初始化 ArrayList,有时我会收到同样的错误消息:

I would do this:

我会这样做:

List<String> myList;

But forget to do this:

但忘记这样做:

myList = new ArrayList();

So just as another thing to think about, make sure you've taken care of all of your housekeeping (making sure variables are initialized/populated, etc...)

因此,作为另一件要考虑的事情,请确保您已经完成了所有内务管理(确保变量已初始化/填充等...)

回答by ostmond

My experience to get rid of a simliar execption in Tomcat 7 is: if you are calling a method in jsf, you will have to add (), even if it does not have a parameter.

我在 Tomcat 7 中摆脱类似执行的经验是:如果您在 jsf 中调用方法,则必须添加 (),即使它没有参数。

This exception but will not appear, if you are using jetty

这个异常但是不会出现,如果你使用jetty

EDIT: Even though this exception was eliminated, it gave another exception:

编辑:即使消除了这个例外,它也给出了另一个例外:

java.lang.NoSuchMethodError: javax.el.ELResolver.invoke(Ljavax/el/ELContext;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Class;[Ljava/lang/Object;)Ljava/lang/Object;

After researching I found the Tomcat 7 brings EL dependency by itself, thus any other dependency in the pom.xml like

经过研究,我发现 Tomcat 7 本身带来了 EL 依赖,因此 pom.xml 中的任何其他依赖,如

<dependency>
    <groupId>javax.el</groupId>
    <artifactId>el-api</artifactId>
    <version>2.2</version>
    <scope>provided</scope>
</dependency>

shoud be removed to avoid the mixing.

应除去以避免混合。

After that, you have to start the tomcat7 by Run as - tomcat7:runin Eclipse, instead of tomcat:runwhich starts by default the tomcat 6.

之后,您必须通过 Run as -tomcat7:run在 Eclipse 中启动 tomcat7 ,而不是tomcat:run默认启动 tomcat 6。

My enviroment:

我的环境:

  • Eclipse Kepler
  • JDK 1.7.0_45
  • Maven 3.1.1
  • 日食开普勒
  • JDK 1.7.0_45
  • Maven 3.1.1