ajax - java.lang.IllegalStateException: es posible que las etiquetas CDATA no se aniden
jsf primefaces (6)
Tengo un problema con una solicitud ajax en una página JSF. Cuando hago clic en el botón, obtengo esta excepción:
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)
Creo que es un problema con los objetos String
, porque cuando codifico las propiedades de la entidad JPA que se muestran en el sitio, todo está bien. Sin embargo, cuando la entidad se recupera de la base de datos (PostgreSQL), lanza la excepción mencionada.
Código 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>
El problema de CDATA no es una pregunta de PrimeFaces pero está relacionado con la implementación de JSF que es responsable de proporcionar el resultado parcial. Reemplazar por su propiedad JSF;)
Mi experiencia para deshacerme de una exención simultánea en Tomcat 7 es: si está llamando a un método en jsf, tendrá que agregar (), incluso si no tiene un parámetro.
Esta excepción, pero no aparecerá, si está utilizando embarcadero
EDITAR: A pesar de que esta excepción fue eliminada, dio otra excepción:
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;
Después de investigar encontré que Tomcat 7 trae la dependencia de EL por sí mismo, por lo tanto, cualquier otra dependencia en el pom.xml como
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
Deben retirarse para evitar la mezcla.
Después de eso, debe iniciar el tomcat7 ejecutando como - tomcat7:run
en Eclipse, en lugar de tomcat:run
que inicia por defecto el tomcat 6.
Mi entorno:
- Eclipse Kepler
- JDK 1.7.0_45
- Maven 3.1.1
Se está produciendo una excepción durante la representación de la respuesta JSF causada por un error en su código. Sin embargo, Mojarra, a su vez, no pudo manejar adecuadamente esta excepción con el controlador de excepciones ajax incorporado, lo que provocó otra excepción que ahora está viendo, ocultando todos los detalles sobre la excepción original.
Mira más de cerca el rastro de la pila. Comience en la parte inferior para rastrear la pila de llamadas:
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
Así, sucedió durante la fase de respuesta de render. Bien, mira la siguiente línea (la que está arriba):
at com.sun.faces.context.AjaxExceptionHandlerImpl.handle(AjaxExceptionHandlerImpl.java:123)
¡Oye, se ha pasado a través del controlador de excepciones ajax AjaxExceptionHandlerImpl
Mojarra AjaxExceptionHandlerImpl
! Esto solo se invoca cuando se produce una excepción durante una solicitud ajax. Bien, lea las siguientes líneas más abajo de arriba a abajo:
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)
Por lo tanto, se intenta escribir la información de error en la respuesta ajax. Esta información tiene que ir en un bloque CDATA. Sin embargo, el inicio de un bloque CDATA falló de la siguiente manera porque aparentemente ya hay un bloque CDATA abierto:
java.lang.IllegalStateException: CDATA tags may not nest
A su vez, esto indica que la excepción se produjo durante la escritura de la respuesta ajax, probablemente porque está ejecutando la lógica de negocios en un método de obtención que solo se invoca durante la generación del resultado HTML. Así que el proceso fue más probable como sigue:
- JSF entra en la fase RENDER_RESPONSE.
- JSF necesita generar salida HTML.
- Para cada
<f:ajax render="some">
(o<p:ajax update="some">
), debe crear un bloque XML<update id="some">
con la salida HTML generada dentro de un bloque CDATA (para mantener la salida XML sintácticamente válida). Por lo tanto, un bloque CDATA necesita ser iniciado. - Al generar la salida HTML en un bloque CDATA, se evalúan todas las expresiones EL de tiempo de procesamiento, incluido el atributo de
value
de todos los componentes de la interfaz de usuario. - En algún lugar, el getter detrás de la expresión EL lanzó una excepción causada por un error en su propio código.
- JSF rápidamente dejó de generar la salida HTML y no cerró el bloque CDATA. La respuesta HTTP contiene datos halfbaked.
- Se activa
AjaxExceptionHandlerImpl
. -
AjaxExceptionHandlerImpl
necesita escribir el detalle de excepción / error en la respuesta. Sin embargo, no comprobó si la respuesta ya está escrita. Intenta ciegamente abrir un bloque CDATA que a su vez falló porque ya está abierto. Lanzó la excepción que está viendo, ocultando todos los detalles sobre la excepción subyacente real que trató de manejar.
Como puedes ver, el problema es doble:
- El renderizador JSF no debería haber dejado la respuesta a medias.
-
AjaxExceptionHandlerImpl
de Mojarra debería haber verificado / verificado el estado de la respuesta.
Si reemplaza el controlador de excepciones ajax integrado de Mojarra por uno personalizado que imprime inmediatamente el seguimiento de la pila , o por OmniFaces FullAjaxExceptionHandler
que es capaz de detectar y limpiar las respuestas ajax de Halfbaked , finalmente revelará y mostrará el subyacente real causado por un error código. Como se dijo antes, lo más probable es que sea causada por la lógica empresarial en un método getter, lo cual es una mala práctica .
Si también ve java.lang.ClassCastException: com.sun.faces.facelets.compiler.UIInstructions cannot be cast to org.primefaces.component.tree.UITreeNode
en el registro del servidor, agregue
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
a /WEB-INF/web.xml
Solo para agregar algo a considerar, a veces puede ser un error muy serio.
Por ejemplo, a veces obtendría este mismo mensaje de error si olvidara inicializar un ArrayList en uno de mis beans que la página xhtml está usando:
Yo haría esto:
List<String> myList;
Pero olvida hacer esto:
myList = new ArrayList();
Así que, como otra cosa en que pensar, asegúrese de que se haya ocupado de todo su mantenimiento (asegurándose de que las variables estén inicializadas / pobladas, etc.)
Tuve el mismo problema que el tuyo. Cuando utilicé el enlace con el componente autocompletado del bean de respaldo, funcionó bien.
<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"/>
y en el frijol de respaldo
private AutoComplete compui;
//compui is initialized when bean is constructed
public AutoComplete getCompui() {
return compui;
}
public void setCompui(AutoComplete compui) {
this.compui = compui;
}