Android Question java.lang.IndexOutOfBoundsException when using StartServiceAt

Michael2150

Member
Licensed User
I have a service that tries to sync events to a server. The service tries syncing it, but if an error occurs the service restarts a certain amount of time later. This only happens a set amount of times before the service gives up and then I use StartServiceAt to start a second service a much later time to try and restart the first service from the beginning trying to sync the events again.
For some unknown reason I get the error "java.lang.IndexOutOfBoundsException: Index: 3, Size: 2" when trying to queue the second service to start.

The global variables:
Sub Process_Globals
    Public AlreadyQueuedToStart As Boolean = False 'This is used to check if the SyncFailedEvent is already queued to start
    Private RetryFailedTime As Int = 0.5 * DateTime.TicksPerMinute 'minutes  The time to wait before retrying to synced a failed event
End Sub

The code where the error happens:
If Not(AlreadyQueuedToStart) Then
Log("Sync failed events queued to start")
StartServiceAtExact(SyncFailedEvents, DateTime.Now + RetryFailedTime ,True)
AlreadyQueuedToStart = True
End If
 

OliverA

Expert
Licensed User
Are you sure that line is causing the error?
 
Upvote 0

DonManfred

Expert
Licensed User
What might be the problem?
Maybe not posting the relevant code.

I don´t see you are accessing a list or array which can raise such errors in the code you posted.

Start with posting the FULL ERROR
 
Upvote 0

Michael2150

Member
Licensed User
This is the whole sub the highlighted line is where the IDE shows the error occurs:
Sub Sync
    If Not(Syncing) Then
        Syncing = True
        ErrorOccured = False
        
        LogColor($"SyncService Starting..."$,Colors.Green)
        
        If File.Exists(File.DirInternal,MapFileSaveName) Then
            RetryMap = File.ReadMap(File.DirInternal,MapFileSaveName)
        End If
        
        UnsyncedEvents = DataAccess.GetEventsWithoutSync
        If UnsyncedEvents.Size = 0 Then StopService(Me)
        
        For Each Event As WorkorderEvent In UnsyncedEvents
            Dim Key As String = Event.id
            Dim Attempts As String = "0"
            If Not(RetryMap.ContainsKey(Key)) Then
                RetryMap.Put(Key,Attempts)
            End If
            Attempts = RetryMap.Get(Key)
            
            If  Attempts >= RetryLimit Then
                LogColor($"Event retry limit reached EventId:${Event.id}"$,Colors.Red)
                DataAccess.InsertRemoteID(0,Event.id)
                RemoveEventFromList(Event)
                RetryMap.Remove(Key)
                
                If Not(AlreadyQueuedToStart) Then
                    Log("Sync failed events queued to start")
                    StartServiceAtExact(SyncFailedEvents, DateTime.Now + RetryFailedTime ,True)
                    AlreadyQueuedToStart = True
                End If
            Else
                LogColor($"Try Sync: EventID: ${Event.id} attempt: ${RetryMap.Get(Key)}"$,Colors.Magenta)
                API.CreateEvent(Event)
                AddOnMap(Event)
            End If
        Next
        If UnsyncedEvents.Size = 0 Then StopService(Me)
    Else
        LogColor($"ShouldTryAgain = True"$,Colors.Yellow)
        ShouldStartAgain = True
    End If
End Sub

That is the whole sub with the line where the IDE says the Error occurs the full error is:


1590576199607.png
 
Upvote 0

OliverA

Expert
Licensed User
Upvote 0

Michael2150

Member
Licensed User
Is this in Debug or Release mode?
The error happens in both modes.. This is really confusing because I'm not really using lists except for the for each loop and the Map. When using a breakpoint at the if statement it runs through without any problems though.
 
Upvote 0

OliverA

Expert
Licensed User
In release mode, when the exception occurs, the exception report (stack trace) will include the line in the syncevents.java file (the source that is produced by B4A in Objects\src\com\eureka\dispatchit folder) where the exception happens. Find the relevant line (for example in the screenshot above, it was line 407) and post it plus some lines above and below.
Note #1: don't post a screenshot, post the lines. Also, post the exception (to verify the line that is causing it).
Note #2: I may have a typo in my source location folder. Don't let that deter you in finding it.
 
Upvote 0

Michael2150

Member
Licensed User
Ah I see I ran it in release mode and got the error:

syncevents_sync (java line: 349)
java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
at java.util.ArrayList.get(ArrayList.java:437)
at anywheresoftware.b4a.objects.collections.List.Get(List.java:117)
at com.eureka.dispatchit.syncevents._sync(syncevents.java:349)
at com.eureka.dispatchit.syncevents._service_start(syncevents.java:315)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:196)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:176)
at com.eureka.dispatchit.syncevents.handleStart(syncevents.java:100)
at com.eureka.dispatchit.syncevents.access$000(syncevents.java:8)
at com.eureka.dispatchit.syncevents$1.run(syncevents.java:71)
at anywheresoftware.b4a.objects.ServiceHelper$StarterHelper.onStartCommand(ServiceHelper.java:237)
at com.eureka.dispatchit.syncevents.onStartCommand(syncevents.java:69)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4298)
at android.app.ActivityThread.access$2700(ActivityThread.java:273)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2070)
at android.os.Handler.dispatchMessage(Handler.java:112)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7625)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)

So I had a look at Java line 349 and found the for each loop


Java code for the for each loop.:
for (; index10 < groupLen10;index10++){
_event = (com.eureka.dispatchit.workorderevent)(group10.Get(index10));
//BA.debugLineNum = 49;BA.debugLine="Dim Key As String = Event.id";
_key = BA.NumberToString(_event._id /*int*/ );
//BA.debugLineNum = 50;BA.debugLine="Dim Attempts As String = \"0\"";
_attempts = "0";
//BA.debugLineNum = 51;BA.debugLine="If Not(RetryMap.ContainsKey(Key)) Then";
if (anywheresoftware.b4a.keywords.Common.Not(_retrymap.ContainsKey((Object)(_key)))) {
//BA.debugLineNum = 52;BA.debugLine="RetryMap.Put(Key,Attempts)";
_retrymap.Put((Object)(_key),(Object)(_attempts));
};
//BA.debugLineNum = 54;BA.debugLine="Attempts = RetryMap.Get(Key)";
_attempts = BA.ObjectToString(_retrymap.Get((Object)(_key)));
//BA.debugLineNum = 56;BA.debugLine="If  Attempts >= RetryLimit Then";
if ((double)(Double.parseDouble(_attempts))>=_retrylimit) {
//BA.debugLineNum = 57;BA.debugLine="LogColor($\"Event retry limit reached EventId:$";
anywheresoftware.b4a.keywords.Common.LogImpl("47536663",("Event retry limit reached EventId:"+anywheresoftware.b4a.keywords.Common.SmartStringFormatter("",(Object)(_event._id /*int*/ ))+""),anywheresoftware.b4a.keywords.Common.Colors.Red);
//BA.debugLineNum = 58;BA.debugLine="DataAccess.InsertRemoteID(0,Event.id)";
mostCurrent._dataaccess._insertremoteid /*String*/ (processBA,(int) (0),_event._id /*int*/ );
//BA.debugLineNum = 59;BA.debugLine="RemoveEventFromList(Event)";
_removeeventfromlist(_event);
//BA.debugLineNum = 60;BA.debugLine="RetryMap.Remove(Key)";
_retrymap.Remove((Object)(_key));
//BA.debugLineNum = 62;BA.debugLine="If Not(AlreadyQueuedToStart) Then";
if (anywheresoftware.b4a.keywords.Common.Not(_alreadyqueuedtostart)) {
//BA.debugLineNum = 63;BA.debugLine="Log(\"Sync failed events queued to start\")";
anywheresoftware.b4a.keywords.Common.LogImpl("47536669","Sync failed events queued to start",0);
//BA.debugLineNum = 64;BA.debugLine="StartServiceAtExact(SyncFailedEvents, DateTim";
anywheresoftware.b4a.keywords.Common.StartServiceAtExact(processBA,(Object)(mostCurrent._syncfailedevents.getObject()),(long) (anywheresoftware.b4a.keywords.Common.DateTime.getNow()+_retryfailedtime),anywheresoftware.b4a.keywords.Common.True);
//BA.debugLineNum = 65;BA.debugLine="AlreadyQueuedToStart = True";
_alreadyqueuedtostart = anywheresoftware.b4a.keywords.Common.True;
};
}else {
//BA.debugLineNum = 68;BA.debugLine="LogColor($\"Try Sync: EventID: ${Event.id} atte";
anywheresoftware.b4a.keywords.Common.LogImpl("47536674",("Try Sync: EventID: "+anywheresoftware.b4a.keywords.Common.SmartStringFormatter("",(Object)(_event._id /*int*/ ))+" attempt: "+anywheresoftware.b4a.keywords.Common.SmartStringFormatter("",_retrymap.Get((Object)(_key)))+""),anywheresoftware.b4a.keywords.Common.Colors.Magenta);
//BA.debugLineNum = 69;BA.debugLine="API.CreateEvent(Event)";
_api._createevent /*String*/ (_event);
//BA.debugLineNum = 70;BA.debugLine="AddOnMap(Event)";
_addonmap(_event);
};
}

The highlighted line is the line 349 the error message included. And i can now see it was the list I used.
 
Upvote 0

OliverA

Expert
Licensed User
For Each Event As WorkorderEvent In UnsyncedEvents
Are you modifying UnsyncedEvents in this For Each Loop? You can't do that. If you delete items of UnsyncedEvents during the For Each processing, you can cause an exception. You need to determine what you want to add/delete from UnsyncedEvents in the For Each loop and then do your additions/deletions outside of the For Each loop.
 
Upvote 0

Michael2150

Member
Licensed User
I think that might be the problem. It makes sense now that I think about it 😅 and I feel stupid. Ill try and fix it and let you know if it worked.
 
Upvote 0

Michael2150

Member
Licensed User
Yes that works perfectly now. Thank you for the help. I've actually never debugged using the Java code. But I'm glad I learned something new though.
 
Upvote 0
Top