Al reiniciar el servidor de aplicaciones JBoss 6.1.0.Final, al segundo request, siempre obtenemos el siguiente error:

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 at java.util.ArrayList.RangeCheck(ArrayList.java:547) at
java.util.ArrayList.get(ArrayList.java:322) at
javax.faces.component.AttachedObjectListHolder.restoreState(AttachedObjectListHolder.java:165) at
javax.faces.component.UIComponentBase.restoreState(UIComponentBase.java:1560) at
com.sun.faces.application.view.StateManagementStrategyImpl$2.visit(StateManagementStrategyImpl.java:276) at
com.sun.faces.component.visit.FullVisitContext.invokeVisitCallback(FullVisitContext.java:151) at
javax.faces.component.UIComponent.visitTree(UIComponent.java:1589) at
javax.faces.component.UIComponent.visitTree(UIComponent.java:1600) at
javax.faces.component.UIComponent.visitTree(UIComponent.java:1600) at
com.sun.faces.application.view.StateManagementStrategyImpl.restoreView(StateManagementStrategyImpl.java:263) at
com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:188) at
com.sun.faces.application.view.ViewHandlingStrategy.restoreView(ViewHandlingStrategy.java:123) at
com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:452) at
com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:148) at
com.ocpsoft.pretty.faces.application.PrettyViewHandler.restoreView(PrettyViewHandler.java:108) at
javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:303) at
javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:303) at
javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:303) at
com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:192) at
com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) at
com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:116) at
com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) at
javax.faces.webapp.FacesServlet.service(FacesServlet.java:409) at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:324) at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242) at
com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:112) at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:274) at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242) at
org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:734) at
org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:541) at
org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:479) at
org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:407) at
com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:103) at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:274) at
org.apache.catalina.core.AppcodelicationFilterChain.doFilter(ApplicationFilterChain.java:242) at
org.jboss.seam.servlet.exception.CatchExceptionFilter.doFilter(CatchExceptionFilter.java:65) at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:274) at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242) at
org.jboss.seam.servlet.event.ServletEventBridgeFilter.doFilter(ServletEventBridgeFilter.java:72) at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:274) at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242) at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) at
org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:181) at
org.jboss.modcluster.catalina.CatalinaContext$RequestListenerValve.event(CatalinaContext.java:285) at
org.jboss.modcluster.catalina.CatalinaContext$RequestListenerValve.invoke(CatalinaContext.java:261) at
org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:88) at
org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:100) at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:159) at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at
org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158) at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at
org.jboss.web.tomcat.service.request.ActiveRequestResponseCacheValve.invoke(ActiveRequestResponseCacheValve.java:53) at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362) at
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) at
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:654) at
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:951) at
java.lang.Thread.run(Thread.java:662)

Estamos usando Seam 3.0.0.Final, y JSF 2 con RichFaces 4.0.0.Final. Éste último es el principal sospechoso del bug, pero se mencionan todos, por que no tenemos si quiera certeza de dónde está.
La verdad que es un bug que viene molestando hace meses y con el que consideramos que no se puede pasar a producción – a pesar que sólo se produce al reiniciar el servidor, por lo que no debiera ser tan común al usuario como al desarrollador…
Dejemos de quitarle el poto a la jeringa.

Según vemos, el método en que se cae pertenece a javax.faces.component.AttachedObjectListHolder por tanto partiremos por bajarnos el código de nuestra implementación de JSF, que actualmente es Mojarra 2.0.3 (creo que pensé cambiarla en algún momento >>, pero como mi web.xml no tiene entrada debe estar tomando el default). Nuestro objeto se encuentra en el jar jsf-api-2.0.3-b05.jar

La fuente está acá >>, y ahora, ¿cómo lo attachamos? Desde eclipse podemos usar el package explorer para navegar los jars de JBoss, entre los cuales (de los últimos) está jsf-api-2.0.3-b.05.jar y ahí, al hacer doble click en alguna de las clases, está el botón Attach Source, le pasamos todo el zip.

El bug efectivamente está en el método restoreState (si quiere ver el código >>)
abajo, al entrar al loop, asume que tiene tantos objetos como es su tamaño, y esto no es así:

//...
else {
// assume 1:1 relation between existing attachedObjects and state
for (int i = 0, len = attachedObjects.length; i < len; i++) {
T l = this.attachedObjects.get(i);
if (l instanceof StateHolder) {
((StateHolder) l).restoreState(context, attachedObjects[i]);
}
}
}

pero attachedObjects tiene algunos de sus valores en null

Ahora, ¿por qué pasa esto? Ésto no necesariamente sea culpa de Mojarra… por ejemplo, aquí les pasaba por culpa de un tag de Seam 2 (s:validateEquality) >> pero dudo que el patch que proveen me sirva, ya que Seam 3 no tiene el componente… probablemente otro componente esté violando la misma asunción.

Espera, y de hecho, attachedObjects no es lo mismo que this.attachedObjects, ¡este último es el que tiene size 0! Según el caso similar que attachedObjects es el estado guardado del UIInput (¿cuál específicamente?, ahí podría estar la clave), que tiene  mientras que this.attachedObjects es la lista de validadores asociados al componente (en este caso, ninguno…)

Viendo qué componente era el que tiraba el error, al principio siempre eran los tag <meta …> así que los eliminé, pero luego sigue pasando con UIOutput…ahora me molesta por los <div>… ¿como que no le gustara el html? ¿puede ser porque nuestro html no es xhtml válido?

Aquí hay otro caso similar debido a <s:validateForm, pero no tiene respuesta >> Del primero, entiendo que ahí el problema era con el EqualityValidator de los UIInput, creo que en nuestro caso es un Validator de los UIOutput
Lo que parece que tiene adentro es un javax.faces.validator.BeanValidator >>, que sirve para efectuar BeanValidation como hemos visto en otros posts…

Recabando datos… otro post al respecto >> avalaría la hipótesis de que esto sale porque nuestras páginas no se conformarían a la especificación xhtml (vimos que los componentes con que se cae son <meta>s y <div>s). Por supuesto, nuestras páginas no son xhtml válido >> pero aquí dicen que JSF nunca ha generado xhtml válido en todo caso >>

Éste es el post >> en que dicen que la solución podría ser deshabilitar javax.faces.PARTIAL_STATE_SAVING en el web.xml

<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>

PARTIAL_STATE_SAVING es un nuevo feature de JSF 2 >> que, en lugar de guardar y restaurar todo el árbol de componentes a cada vez, permite marcarle un estado inicial e ir guardando solamente las diferencias. Ésto a través de la interfaz PartialStateHolder, que implementa cada componente (y de paso, también nuestro AttachedObjectListHolder).
Deshabilitándolo efectivamente el error desparece (nunca pasa por el código). Sin embargo, ello implica una refactorización general de la aplicación. Por ejemplo, los mantenedores buscan con un request de retraso (probablemente porque son @ViewScoped) y ciertas acciones se caen por NPE (probablemente las que son por ajax). Además, estamos haciendo JSF mucho menos eficiente…

Tal vez otra opción es hacerle un pequeño patch a AttachedObjectListHolder… para eso, simplemente le agrego un check

else {
// assume 1:1 relation between existing attachedObjects and state
for (int i = 0, len = attachedObjects.length; i < len; i++) {
//HACK MIRÓ bit.ly/MjWTbQ
if(i<=this.attachedObjects.size()){
T l = this.attachedObjects.get(i);
if (l instanceof StateHolder) {
((StateHolder) l).restoreState(context, attachedObjects[i]);
}
}
}
}

y luego tengo que recompilar las fuentes…

Dentro del directorio viene un archivo build.xml, por tanto imagino que se hace con ant. Pero llegar y ejecutar ant no funciona, porque reclama que no sabe qué es ${jsf.build.home}… Siguiendo estas instrucciones >>, copiamos el archivo build.properties.glassfish a build.properties y en ${jsf.build.home} le damos la ruta los fuentes.

Este sitio utiliza cookies.    Leer más