Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 #3245

Closed
ren-zhijun-oracle opened this issue Apr 11, 2014 · 31 comments
Closed

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 #3245

ren-zhijun-oracle opened this issue Apr 11, 2014 · 31 comments
Assignees

Comments

@ren-zhijun-oracle
Copy link
Contributor

IndexOutOfBoundsException caused by javax.faces.component.AttachedObjectListHolder::restoreState(FacesContext context, Object state)

Affected Versions

[2.2.6]

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
Reported by thomas.meister

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
thomas.meister said:
} 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;
if (l instanceof StateHolder)

{ ((StateHolder) l).restoreState(context, attachedObjects[i]); }

}
}

// this.attachedObjects seems to be empty whereas state contains some objects in my case....

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
thomas.meister said:
my error stacktrace:

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:604)
at java.util.ArrayList.get(ArrayList.java:382)
at javax.faces.component.AttachedObjectListHolder.restoreState(AttachedObjectListHolder.java:165)
at javax.faces.component.UIInput.restoreState(UIInput.java:1423)
at com.sun.faces.application.view.FaceletPartialStateManagementStrategy$2.visit(FaceletPartialStateManagementStrategy.java:380)
at com.sun.faces.component.visit.FullVisitContext.invokeVisitCallback(FullVisitContext.java:151)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1689)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UINamingContainer.visitTree(UINamingContainer.java:163)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UINamingContainer.visitTree(UINamingContainer.java:163)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIForm.visitTree(UIForm.java:371)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at com.sun.faces.application.view.FaceletPartialStateManagementStrategy.restoreView(FaceletPartialStateManagementStrategy.java:367)
at com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:138)
at com.sun.faces.application.view.ViewHandlingStrategy.restoreView(ViewHandlingStrategy.java:123)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:572)
at com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:148)
at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:353)
at org.omnifaces.viewhandler.RestorableViewHandler.restoreView(RestorableViewHandler.java:66)
at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:353)
at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:197)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:121)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
:
:

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
@manfredriem said:
Please send a reproducer in a zip file to issues@javaserverfaces.java.net. Thanks!

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
thomas.meister said:
I tried to create a reproducer within a zip, but our project env is too complex. But I can reproduce it consequently. In case of IndexOutOfBoundsException my state param contains an object array containing a beanvalidation (JSF303) group instance (?!?), while this.attachedObjects is empty.

An additional size-check of this.attachedObjects solves my problem (see attached patch file).

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
thomas.meister said:
Index: src/main/java/javax/faces/component/AttachedObjectListHolder.java
<+>UTF-8

— src/main/java/javax/faces/component/AttachedObjectListHolder.java (revision )
+++ src/main/java/javax/faces/component/AttachedObjectListHolder.java (revision )
@@ -40,12 +40,13 @@

package javax.faces.component;

-import javax.faces.context.FacesContext;
-import java.util.List;
-import java.util.ArrayList;
import java.lang.reflect.Array;
+import java.util.ArrayList;
import java.util.Iterator;
+import java.util.List;

+import javax.faces.context.FacesContext;
+
/**

  • Utility class to enable partial state saving of Lists of attached objects
    @@ -163,10 +164,12 @@
    } else {
    // assume 1:1 relation between existing attachedObjects and state
    for (int i = 0, len = attachedObjects.length; i < len; i++) {

    • if (this.attachedObjects.size() > i) {
  • T l = this.attachedObjects.get;

  • if (l instanceof StateHolder) {

  • ((StateHolder) l).restoreState(context, attachedObjects[i]);

    • T l = this.attachedObjects.get;
    • if (l instanceof StateHolder) { + ((StateHolder) l).restoreState(context, attachedObjects[i]); + }
  • }

    • }
      }
      }

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
@manfredriem said:
I am sorry but unless I have a reproducer that does not include any external dependencies I cannot just apply this patch. Unfortunately sometimes a 3rd party library does things that are not entirely correct. I need to make sure this is not the case.

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
thomas.meister said:
Perhaps a 3rd party library is not entirely correct, but an IndexOutOfBoundsException is really waste.

A check of the boundaries of this.attachedObjects would really help in this situation.

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
@manfredriem said:
Thomas, while I understand your point of view. If we apply this fix without understanding why you are getting this in the first place we potentially open ourselves to even worse problems. The error you are seeing should not happen in the first place. What gets saved should be restored. So if there is a problem there we need to know why this is happening. Hence why we ask for a reproducer.

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
hwellmann said:
I'm seeing the same exception in a different context, running load tests on my application. The exception starts occurring when the number of concurrent requests exceeds a certain threshold.

The exception does not occur when javax.faces.PARTIAL_STATE_SAVING is set to false. Do you have any regression tests checking the thread-safety of partial state saving?

My environment: WildFly 8.0.0.Final (including Mojarra 2.2.5), Oracle Java 1.8.0_05.

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
thomas.meister said:
Could not reproduce after putting all validateBean-tags inside corresponding input-elements. Previously we had facelet structures with validateBean-tags surrounding multiple input-elements. Although it seemed to work we determined sporadic IndexOutOfBoundsExceptions.

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
@manfredriem said:
While I really would like to apply this I cannot do that without a reproducer. As stated by the reporter the exceptions disappeared for them by rewriting their pages slightly. Closing this as "Incomplete"

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
pjot said:
Hello, im having the similar issue while dynamically adding a validator to UIInput components. Branch: MOJARRA_2_2X_ROLLING/2.9.9-SNAPSHOT. Isend a reproducer to issues@javaserverfaces.java.net. Should i open a new Issue?

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
@edburns said:
Reopening to attach requested reproducer. Thanks.

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
ren.zhijun.oracle said:
call for review.

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
@edburns said:
I can't in good faith simply agree to this patch because it appears to work around the problem rather than solving it.

A proper solution would account for the fact that RequiredValidator does not implement StateHolder (see JAVASERVERFACES_SPEC_PUBLIC-1279) and take the necessary action, namely to serialize the instance.

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
@edburns said:
Also, thank you for the very excellent test case. I appreciate you using the archetype. Bravo.

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
@manfredriem said:
Please do not create a new web application for each test case. This test case belongs in the test/servlet30/facelets/core project. Please rework the change bundle to accommodate this. Thanks!

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
ren.zhijun.oracle said:
Hi Ed,

Actually, the fact that RequiredValidator is not a StateHolder, is not the main reason which cause this issue.

Currently the class AttachedObjectListHolder's initialState is not designed clearly, e.g., one variable for multiple validators.

I found a simple way to fix the issue and the solution is based on the assumption that the dynamically added validators should be kept between requests in the same session, I attache the changebundle here for your review.
if the assumption is not correct, I think the behavior need to be defined clearly and the class AttachedObjectListHolder need to be redesigned.

Thanks,
Zhijun

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
File: 20140911-1934Z-i_moj_3241-changebundle.txt
Attached By: @edburns

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
@edburns said:
Remove .svn directories from zip to prevent problems when unzipping. Snapshot before applying Zhijun's 2014-09-11 version of the fix.

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
File: 20141008-1517Z-i_moj_3241-edburns.zip
Attached By: @edburns

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
@edburns said:
Thanks for your patience and persistence with this fix. I agree with your fix from 2014-09-11 07:45 JIRA time. Please run all the tests before committing and be very careful to not commit any of those "property changes only" modifications. You can svn revert those before committing.

r=edburns.

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
ren.zhijun.oracle said:
rzhijun-mac:MOJARRA_2_2X_ROLLING zhijun$ svn status |grep -v '^?'
M jsf-api/src/main/java/javax/faces/component/AttachedObjectListHolder.java
A test/servlet30/facelets/core/src/main/java/com/sun/faces/test/servlet30/facelets/core/DynamicValidatorBean.java
A test/servlet30/facelets/core/src/main/webapp/dynamicValidator.xhtml
A test/servlet30/facelets/core/src/test/java/com/sun/faces/test/servlet30/facelets/core/Issue3241IT.java
rzhijun-mac:MOJARRA_2_2X_ROLLING zhijun$ svn commit -m "https://java.net/jira/browse/JAVASERVERFACES-3241" --username ren.zhijun.oracle
Sending jsf-api/src/main/java/javax/faces/component/AttachedObjectListHolder.java
Adding test/servlet30/facelets/core/src/main/java/com/sun/faces/test/servlet30/facelets/core/DynamicValidatorBean.java
Adding test/servlet30/facelets/core/src/main/webapp/dynamicValidator.xhtml
Adding test/servlet30/facelets/core/src/test/java/com/sun/faces/test/servlet30/facelets/core/Issue3241IT.java
Transmitting file data ....
Committed revision 13732.

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
umbra said:
I still see this using 2.2.9

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
	at java.util.ArrayList.rangeCheck(ArrayList.java:635)
	at java.util.ArrayList.get(ArrayList.java:411)
	at javax.faces.component.AttachedObjectListHolder.restoreState(Unknown Source)
	at javax.faces.component.UIComponentBase.restoreState(Unknown Source)
	at com.sun.faces.application.view.FaceletPartialStateManagementStrategy$2.visit(Unknown Source)
	at com.sun.faces.component.visit.FullVisitContext.invokeVisitCallback(Unknown Source)
	at javax.faces.component.UIComponent.visitTree(Unknown Source)
	at javax.faces.component.UIComponent.visitTree(Unknown Source)
	at javax.faces.component.UIComponent.visitTree(Unknown Source)
	at javax.faces.component.UIComponent.visitTree(Unknown Source)
	at com.sun.faces.application.view.FaceletPartialStateManagementStrategy.restoreView(Unknown Source)
	at com.sun.faces.application.StateManagerImpl.restoreView(Unknown Source)
	at com.sun.faces.application.view.ViewHandlingStrategy.restoreView(Unknown Source)
	at com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(Unknown Source)
	at com.sun.faces.application.view.MultiViewHandler.restoreView(Unknown Source)
	at javax.faces.application.ViewHandlerWrapper.restoreView(Unknown Source)
	at com.sun.faces.lifecycle.RestoreViewPhase.execute(Unknown Source)
	at com.sun.faces.lifecycle.Phase.doPhase(Unknown Source)
	at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(Unknown Source)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(Unknown Source)
	at javax.faces.webapp.FacesServlet.service(Unknown Source)

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
umbra said:
And on 2.2.10 (with line numbers now)

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
       at java.util.ArrayList.rangeCheck(ArrayList.java:635)
       at java.util.ArrayList.get(ArrayList.java:411)
       at javax.faces.component.AttachedObjectListHolder.restoreState(AttachedObjectListHolder.java:166)
       at javax.faces.component.UIComponentBase.restoreState(UIComponentBase.java:1611)
       at com.sun.faces.application.view.FaceletPartialStateManagementStrategy$2.visit(FaceletPartialStateManagementStrategy.java:379)
       at com.sun.faces.component.visit.FullVisitContext.invokeVisitCallback(FullVisitContext.java:151)
       at javax.faces.component.UIComponent.visitTree(UIComponent.java:1689)
       at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
       at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
       at com.sun.faces.application.view.FaceletPartialStateManagementStrategy.restoreView(FaceletPartialStateManagementStrategy.java:366)
       at com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:138)
       at com.sun.faces.application.view.ViewHandlingStrategy.restoreView(ViewHandlingStrategy.java:123)
       at com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:586)
       at com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:150)
       at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:353)
       at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:197)
       at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
       at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:121)
       at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
       at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)

Can we reopen this or should I create a new ticket?

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
ren.zhijun.oracle said:
Hi Andrei,

Can you attach your application here to reproduce the issue?

In my commitment in -r13723, there was an test case which verify the issue has been fixed. so I need you to provide a reproducer to do the investigation.

BR,
Zhijun

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
umbra said:
Hm,
After 2 long days of trying to create an app to reproduce the issue, I've reached the conclusion that it was caused by my attempt to improve the handling of "redirect to the initial URL after form login" for AJAX requests.

This is what I think was happening:

  • load a page with an ajax poll component to refresh some sections of the page
  • on a separate window/tab, logout of the app to destroy the session
  • the poll component makes an ajax call which gets redirected to the login page (also JSF), the JSF servlet creates the state and returns the IDs in a partial update XML
  • in that 2nd tab, login back in the app
  • in the 1st tab, the poll components continues making calls which now try to restore the state obtained from the login form view

After removing my dirty hack (and replacing it with the correct fix inspired from this post, which was clearing the JSF headers and parameters that marking the request as a partial update ajax call, I now get a proper ViewExpiredException.

Sorry for the noise

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
michaelbreu said:
Sorry to comment on a closed issue, however I'm able to reproduce this problem with 2.2.13 .

I just debugged through the relevant statements

**Bar.java**            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]);
}
            }

There seems to be a "code smell": attachedObjects and this.attachedObjects are two different objects.

Could someone have a look on it?

@ren-zhijun-oracle
Copy link
Contributor Author

@javaserverfaces Commented
@ruolli said:
Please try updating loop to below :

for (int i = 0, len = this.attachedObjects.size(); i < len; i++) {
  T l = this.attachedObjects.get(i);
  if (l instanceof StateHolder) {
      ((StateHolder) l).restoreState(context, attachedObjects[i]);
  }   
              }

@ren-zhijun-oracle
Copy link
Contributor Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants