Подтвердить что ты не робот

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>
4b9b3361

Ответ 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