Java.lang.IllegalStateException: теги CDATA могут не входить
У меня проблема с запросом ajax на странице JSF. Когда я нажимаю на кнопку, я получаю это исключение:
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, которые отображаются на сайте, тогда все в порядке. Однако, когда объект извлекается из базы данных (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>
Ответы
Ответ 1
Там исключается исключение во время рендеринга ответа 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
! Это только, вызываемое при возникновении исключения во время запроса 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">
) ему необходимо создать XML-блок <update id="some">
с генерируемым выходом HTML внутри блока CDATA (до сохранить синтаксически корректный вывод XML). Поэтому необходимо запустить блок CDATA.
- При генерации вывода HTML в CDATA-блок вычисляются все EL-выражения рендеринга, включая атрибут
value
всех компонентов пользовательского интерфейса.
- Где-то, получатель за выражением EL выкинул исключение, вызванное ошибкой в вашем собственном коде.
- JSF быстро прекратил генерировать вывод HTML и не закрывал блок CDATA. Ответ HTTP содержит полуобработанные данные.
-
AjaxExceptionHandlerImpl
.
-
AjaxExceptionHandlerImpl
необходимо написать описание исключения/ошибки в ответ. Однако он не проверял, написано ли ответ. Он слепо пытается открыть блок CDATA, который, в свою очередь, потерпел неудачу, потому что он уже открыт. Он бросил исключение, которое вы видите, скрывая все детали о реальном базовом исключении, которое он пытался обработать.
Как вы можете видеть, проблема двояка:
- Средство рендеринга JSF не должно оставлять ответ полузакрытым.
- Mojarra
AjaxExceptionHandlerImpl
должен проверить/проверить состояние ответа.
Если вы замените Mojarra встроенный ajax обработчик исключений на пользовательский, который сразу же распечатает трассировку стека, или OmniFaces FullAjaxExceptionHandler
, который способен обнаруживать и очищать полузакрытые ответы ajax, тогда он, наконец, откроет и покажет реальное основание, вызванное ошибкой в вашем коде. Как было сказано ранее, это скорее всего вызвано выполнением бизнес-логики в методе геттера, что является плохим методом.
Ответ 2
У меня была такая же проблема, как и у вас. Когда я использовал привязку с компонентом автозаполнения из базы данных 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;
}
Ответ 3
Проблема с CDATA не является вопросом PrimeFaces, а связана с реализацией JSF, которая несет ответственность за предоставление частичного вывода. замените им свойство JSF;)
Ответ 4
Если вы также видите 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
Ответ 5
Просто, чтобы бросить кое-что, чтобы рассмотреть, также, иногда это может быть действительно костяной ошибкой.
Например, иногда я получал бы это же сообщение об ошибке, если бы забыл инициализировать ArrayList в одном из моих beans, которые использует страница xhtml:
Я бы сделал это:
List<String> myList;
Но забудьте сделать это:
myList = new ArrayList();
Так же, как и другое, о чем нужно подумать, убедитесь, что вы позаботились о своем домашнем хозяйстве (убедитесь, что переменные инициализированы/заполнены и т.д.)
Ответ 6
Мой опыт избавиться от выполнения simliar в Tomcat 7: если вы вызываете метод в jsf, вам нужно будет добавить(), даже если у него нет параметра.
Это исключение, но не появится, если вы используете причал
EDIT: Несмотря на то, что это исключение было устранено, оно дало другое исключение:
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>
shoud удалить, чтобы избежать смешивания.
После этого вам нужно запустить tomcat7 с помощью Run as - tomcat7:run
в Eclipse вместо tomcat:run
, который по умолчанию запускает tomcat 6.
Мое окружение:
- Eclipse Kepler
- JDK 1.7.0_45
- Maven 3.1.1