我有一个问题,在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)
我认为这是一些问题String
对象,因为当我硬编码并显示在相关网站上的JPA实体属性,那么一切都OK。 然而,当该实体是从数据库(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>
有渲染造成的代码中的错误的JSF反应过程中被抛出的异常。 然而,钻嘴鱼科又未能妥善处理这一异常,并内置AJAX异常处理程序,从而导致另一个异常,你现在看到的,躲着走对原以外的所有细节。
看看堆栈跟踪近。 在底部开始跟踪调用堆栈:
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
因此,它的发生期间显示响应阶段。 好吧,看看下一行(一个上面):
at com.sun.faces.context.AjaxExceptionHandlerImpl.handle(AjaxExceptionHandlerImpl.java:123)
嘿,这是通过钻嘴鱼科的内置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)
它因此试图写入错误信息到Ajax响应。 该信息在CDATA块去。 但是,在开始CDATA块失败如下因为已经有很显然是一个CDATA块打开:
java.lang.IllegalStateException: CDATA tags may not nest
这反过来表明,编写Ajax响应,很可能是因为你在一个getter方法,该方法生成HTML输出时只被调用执行业务逻辑期间发生异常。 所以这个过程是最有可能如下:
- JSF进入RENDER_RESPONSE相。
- JSF需要生成HTML输出。
- 对于每一个
<f:ajax render="some">
或<p:ajax update="some">
它需要创建一个<update id="some">
与内部生成的HTML输出XML块CDATA块 (保持XML输出语法有效)。 因此,一个CDATA块需要启动。 - 在产生HTML输出到CDATA块,所有渲染时间EL表达式进行求值,包括
value
的所有UI组件的属性。 - 冥冥之中,EL表达式背后,吸气扔造成在自己的代码中的错误的异常。
- JSF及时制止生成HTML输出,并没有关闭CDATA块。 HTTP响应包含halfbaked数据。
-
AjaxExceptionHandlerImpl
被触发。 -
AjaxExceptionHandlerImpl
需要写异常/错误详细的回应。 然而,它并没有检查,如果响应已经写入。 它盲目地尝试打开一个CDATA块,又失败了,因为它已经打开。 它扔了你所看到的例外,躲着走对真正的根本例外它试图处理所有的细节。
正如你所看到的,这个问题有两方面:
- JSF渲染器不应该离开halfbaked的响应。
- 钻嘴鱼科的
AjaxExceptionHandlerImpl
应该检查/检验响应的状态。
如果您通过更换钻嘴鱼科的内置AJAX异常处理程序自定义的其立即打印堆栈跟踪 ,或由OmniFaces FullAjaxExceptionHandler
,它能够检测和清除halfbaked Ajax响应 ,那么它最终将揭示和展现真正由一个bug底层引起的码。 正如前面所说的,它是最有可能造成在一个getter方法,这是一种不好的做法,执行业务逻辑 。
我有同样的问题,因为你,当我使用自动完成组件与支持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"/>
而在后台bean
private AutoComplete compui;
//compui is initialized when bean is constructed
public AutoComplete getCompui() {
return compui;
}
public void setCompui(AutoComplete compui) {
this.compui = compui;
}
CDATA问题不是一个PrimeFaces问题,而是关系到JSF执行谁负责提供部分输出的。 通过它的JSF财产更换;)
如果你也看到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>
到/WEB-INF/web.xml
只是在扔东西要考虑为好,有时也可以是一个真正的骨为首的错误。
例如,有时我会,如果我忘了在我的豆谓之XHTML页面使用的一个初始化一个ArrayList收到此相同的错误信息:
我这样做:
List<String> myList;
但是忘记这样做:
myList = new ArrayList();
因此,正如其他的事情想想,确保你已经照顾你所有的看家的(确保变量初始化/填充,等...)
我的经验,以摆脱的Tomcat 7 simliar execption的是:如果你调用JSF的方法,你必须添加(),即使它没有一个参数。
此异常,但不会出现,如果您使用的码头
编辑:尽管此异常被淘汰,这给了另一个异常:
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;
经过研究,我发现Tomcat的7带来EL依赖本身,因此,任何其他依赖于类似的pom.xml
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
768,16被移除,以避免在混合。
在这之后,你必须开始通过运行tomcat7为- tomcat7:run
,而不是在Eclipse中tomcat:run
其默认启动Tomcat的6。
我的环境:
- Eclipse的开普勒
- JDK 1.7.0_45
- Maven的3.1.1