J'ai un problème avec une demande ajax dans une page JSF. Lorsque je clique sur le bouton, j'obtiens cette exception:
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)
Je pense que c'est un problème avec les objets String
, car quand je code les propriétés d'entité JPA qui sont affichées sur le site, tout est OK. Cependant, lorsque l'entité est extraite de la base de données (PostgreSQL), elle lève l'exception susmentionnée.
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>
Une exception est générée lors du rendu de la réponse JSF provoquée par un bogue dans votre code. Cependant, Mojarra à son tour n'a pas réussi à gérer cette exception avec le gestionnaire d'exceptions ajax intégré, provoquant une autre exception que vous voyez maintenant, masquant tous les détails de l'exception d'origine.
Regardez de plus près la trace de la pile. Commencez par le bas pour suivre la pile d'appels:
at com.Sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.Java:139)
Ainsi, cela s’est passé pendant la phase de réponse au rendu. Ok, regardez la ligne suivante (celle au-dessus):
at com.Sun.faces.context.AjaxExceptionHandlerImpl.handle(AjaxExceptionHandlerImpl.Java:123)
Salut, il a été passé par le gestionnaire d'exceptions ajax intégré à Mojarra AjaxExceptionHandlerImpl
! Only est invoqué lorsqu'une exception s'est produite lors d'une demande ajax. D'accord, lisez les lignes suivantes plus en avant de bas en haut:
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)
Il tente donc d'écrire les informations d'erreur dans la réponse ajax. Cette information doit aller dans un bloc CDATA. Cependant, le démarrage d'un bloc CDATA a échoué comme suit, car il semble qu'un bloc CDATA soit déjà ouvert:
Java.lang.IllegalStateException: CDATA tags may not nest
Cela indique à son tour que l'exception s'est produite lors de l'écriture de la réponse ajax, probablement parce que vous exécutez une logique métier dans une méthode de lecture qui n'est appelée que lors de la génération de la sortie HTML. Le processus était donc probablement le suivant:
<f:ajax render="some">
(ou <p:ajax update="some">
), il doit créer un bloc XML <update id="some">
avec la sortie HTML générée dans un bloc CDATA (pour que la sortie XML soit syntaxiquement valide). Donc, un bloc CDATA doit être démarré.value
de tous les composants de l'interface utilisateur.AjaxExceptionHandlerImpl
est déclenché.AjaxExceptionHandlerImpl
doit écrire le détail de l'exception/de l'erreur dans la réponse. Cependant, il n'a pas vérifié si la réponse est déjà écrite. Il tente aveuglément d'ouvrir un bloc CDATA qui a échoué car il est déjà ouvert. Il a jeté l'exception que vous voyez en cachant tous les détails de la véritable exception sous-jacente qu'il a essayé de gérer.Comme vous pouvez le constater, le problème est double:
AjaxExceptionHandlerImpl
de Mojarra aurait dû vérifier/vérifier l'état de la réponse.Si vous remplacez le gestionnaire d'exceptions ajax intégré de Mojarra par un custom qui imprime immédiatement la trace de pile , ou par OmniFaces FullAjaxExceptionHandler
qui est capable de détecter et de nettoyer les réponses ajax saccadées , il sera finalement révélé et affiché réel sous-jacent causé par un bug dans votre code. Comme indiqué précédemment, il est fort probable que exécute une logique métier dans une méthode getter, ce qui est une mauvaise pratique .
J'ai eu le même problème que le vôtre. Lorsque j'ai utilisé la liaison avec le composant autocomplete du bean de support, cela a bien fonctionné.
<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"/>
et dans le haricot
private AutoComplete compui;
//compui is initialized when bean is constructed
public AutoComplete getCompui() {
return compui;
}
public void setCompui(AutoComplete compui) {
this.compui = compui;
}