B4J Question Recursive method does work with a breakpoint, but not without it

alwaysbusy

Expert
Licensed User
Longtime User
This is been driving me crazy the whole day.

I have some recursive function GetInnerFilter() in the JSONPath class that only seems to work if I put a breakpoint in the code, even if set at code that is not used. So of course, in release mode it does not work too.

Without a breakpoint:

1726486032784.png


GamePlayers is empty.

If I put in this Breakpoint (is in code the function never has to use in this case, so it just goes without even stopping at the breakpoint:

1726486092626.png


Then, the result is correct:

1726486108235.png


I don't use CallSub, CallSubDelayed or any Resumable sub. But it does use a JSONParser inside the recursive function.

@Erel Does the Initialize of the JSONParser maybe run in a seperate thread? No idea really what could be causing this so it may be a wild guess.

Attached is the project.

Alwaysbusy
 

Attachments

  • JSONPathTeamCup.zip
    6.2 KB · Views: 20
Last edited:

PaulMeuris

Active Member
Licensed User
Waiting for debugger to connect...
Program started.
obj: {keys={playerId=10, teamId=2, gameId=2}, teams=[{name=De Caddie Clan, id=1, players=[{id=1, name=Bailleul Alain, isCaptain=true, isRabbit=false}, {id=2, name=Lampaert Greet, isCaptain=false, isRabbit=false}, {id=3, name=Descamps Francis, isCaptain=false, isRabbit=false}, {id=4, name=White Gerard, isCaptain=false, isRabbit=false}, {id=5, name=Brion Catherine, isCaptain=false, isRabbit=true}]}, {name=De Caddie Clan 2, id=2, players=[{id=6, name=Bailleul Alain 2, isCaptain=true, isRabbit=false}, {id=7, name=Lampaert Greet 2, isCaptain=false, isRabbit=false}, {id=8, name=Descamps Francis 2, isCaptain=false, isRabbit=false}, {id=9, name=White Gerard 2, isCaptain=false, isRabbit=false}, {id=10, name=Brion Catherine 2, isCaptain=false, isRabbit=true}]}], games=[{id=1, name=1-apr, teams=[{teamId=1, scores=[{playerId=1, typeGame=, score=0}, {playerId=2, typeGame=, score=0}, {playerId=3, typeGame=, score=0}, {playerId=4, typeGame=, score=0}, {playerId=5, typeGame=, score=0}]}, {teamId=2, scores=[{playerId=6, typeGame=, score=0}, {playerId=7, typeGame=, score=0}, {playerId=8, typeGame=, score=0}, {playerId=9, typeGame=, score=0}, {playerId=10, typeGame=, score=0}]}]}, {id=2, name=2-apr, teams=[{teamId=1, scores=[{playerId=1, typeGame=, score=0}, {playerId=2, typeGame=, score=0}, {playerId=3, typeGame=, score=0}, {playerId=4, typeGame=, score=0}, {playerId=5, typeGame=, score=0}]}, {teamId=2, scores=[{playerId=6, typeGame=, score=0}, {playerId=7, typeGame=, score=0}, {playerId=8, typeGame=, score=0}, {playerId=9, typeGame=, score=0}, {playerId=10, typeGame=, score=0}]}]}]}
obj: [{name=De Caddie Clan, id=1, players=[{id=1, name=Bailleul Alain, isCaptain=true, isRabbit=false}, {id=2, name=Lampaert Greet, isCaptain=false, isRabbit=false}, {id=3, name=Descamps Francis, isCaptain=false, isRabbit=false}, {id=4, name=White Gerard, isCaptain=false, isRabbit=false}, {id=5, name=Brion Catherine, isCaptain=false, isRabbit=true}]}, {name=De Caddie Clan 2, id=2, players=[{id=6, name=Bailleul Alain 2, isCaptain=true, isRabbit=false}, {id=7, name=Lampaert Greet 2, isCaptain=false, isRabbit=false}, {id=8, name=Descamps Francis 2, isCaptain=false, isRabbit=false}, {id=9, name=White Gerard 2, isCaptain=false, isRabbit=false}, {id=10, name=Brion Catherine 2, isCaptain=false, isRabbit=true}]}]
obj: {name=De Caddie Clan, id=1, players=[{id=1, name=Bailleul Alain, isCaptain=true, isRabbit=false}, {id=2, name=Lampaert Greet, isCaptain=false, isRabbit=false}, {id=3, name=Descamps Francis, isCaptain=false, isRabbit=false}, {id=4, name=White Gerard, isCaptain=false, isRabbit=false}, {id=5, name=Brion Catherine, isCaptain=false, isRabbit=true}]}
obj: [{id=1, name=Bailleul Alain, isCaptain=true, isRabbit=false}, {id=2, name=Lampaert Greet, isCaptain=false, isRabbit=false}, {id=3, name=Descamps Francis, isCaptain=false, isRabbit=false}, {id=4, name=White Gerard, isCaptain=false, isRabbit=false}, {id=5, name=Brion Catherine, isCaptain=false, isRabbit=true}]
obj: {id=1, name=Bailleul Alain, isCaptain=true, isRabbit=false}
obj: {id=2, name=Lampaert Greet, isCaptain=false, isRabbit=false}
obj: {id=3, name=Descamps Francis, isCaptain=false, isRabbit=false}
obj: {id=4, name=White Gerard, isCaptain=false, isRabbit=false}
obj: {id=5, name=Brion Catherine, isCaptain=false, isRabbit=true}
obj: {name=De Caddie Clan 2, id=2, players=[{id=6, name=Bailleul Alain 2, isCaptain=true, isRabbit=false}, {id=7, name=Lampaert Greet 2, isCaptain=false, isRabbit=false}, {id=8, name=Descamps Francis 2, isCaptain=false, isRabbit=false}, {id=9, name=White Gerard 2, isCaptain=false, isRabbit=false}, {id=10, name=Brion Catherine 2, isCaptain=false, isRabbit=true}]}
obj: [{id=6, name=Bailleul Alain 2, isCaptain=true, isRabbit=false}, {id=7, name=Lampaert Greet 2, isCaptain=false, isRabbit=false}, {id=8, name=Descamps Francis 2, isCaptain=false, isRabbit=false}, {id=9, name=White Gerard 2, isCaptain=false, isRabbit=false}, {id=10, name=Brion Catherine 2, isCaptain=false, isRabbit=true}]
obj: {id=6, name=Bailleul Alain 2, isCaptain=true, isRabbit=false}
obj: {id=7, name=Lampaert Greet 2, isCaptain=false, isRabbit=false}
obj: {id=8, name=Descamps Francis 2, isCaptain=false, isRabbit=false}
obj: {id=9, name=White Gerard 2, isCaptain=false, isRabbit=false}
obj: {id=10, name=Brion Catherine 2, isCaptain=false, isRabbit=true}
obj: {keys={playerId=10, teamId=2, gameId=2}, teams=[{name=De Caddie Clan, id=1, players=[{id=1, name=Bailleul Alain, isCaptain=true, isRabbit=false}, {id=2, name=Lampaert Greet, isCaptain=false, isRabbit=false}, {id=3, name=Descamps Francis, isCaptain=false, isRabbit=false}, {id=4, name=White Gerard, isCaptain=false, isRabbit=false}, {id=5, name=Brion Catherine, isCaptain=false, isRabbit=true}]}, {name=De Caddie Clan 2, id=2, players=[{id=6, name=Bailleul Alain 2, isCaptain=true, isRabbit=false}, {id=7, name=Lampaert Greet 2, isCaptain=false, isRabbit=false}, {id=8, name=Descamps Francis 2, isCaptain=false, isRabbit=false}, {id=9, name=White Gerard 2, isCaptain=false, isRabbit=false}, {id=10, name=Brion Catherine 2, isCaptain=false, isRabbit=true}]}], games=[{id=1, name=1-apr, teams=[{teamId=1, scores=[{playerId=1, typeGame=, score=0}, {playerId=2, typeGame=, score=0}, {playerId=3, typeGame=, score=0}, {playerId=4, typeGame=, score=0}, {playerId=5, typeGame=, score=0}]}, {teamId=2, scores=[{playerId=6, typeGame=, score=0}, {playerId=7, typeGame=, score=0}, {playerId=8, typeGame=, score=0}, {playerId=9, typeGame=, score=0}, {playerId=10, typeGame=, score=0}]}]}, {id=2, name=2-apr, teams=[{teamId=1, scores=[{playerId=1, typeGame=, score=0}, {playerId=2, typeGame=, score=0}, {playerId=3, typeGame=, score=0}, {playerId=4, typeGame=, score=0}, {playerId=5, typeGame=, score=0}]}, {teamId=2, scores=[{playerId=6, typeGame=, score=0}, {playerId=7, typeGame=, score=0}, {playerId=8, typeGame=, score=0}, {playerId=9, typeGame=, score=0}, {playerId=10, typeGame=, score=0}]}]}]}
obj: [{id=1, name=1-apr, teams=[{teamId=1, scores=[{playerId=1, typeGame=, score=0}, {playerId=2, typeGame=, score=0}, {playerId=3, typeGame=, score=0}, {playerId=4, typeGame=, score=0}, {playerId=5, typeGame=, score=0}]}, {teamId=2, scores=[{playerId=6, typeGame=, score=0}, {playerId=7, typeGame=, score=0}, {playerId=8, typeGame=, score=0}, {playerId=9, typeGame=, score=0}, {playerId=10, typeGame=, score=0}]}]}, {id=2, name=2-apr, teams=[{teamId=1, scores=[{playerId=1, typeGame=, score=0}, {playerId=2, typeGame=, score=0}, {playerId=3, typeGame=, score=0}, {playerId=4, typeGame=, score=0}, {playerId=5, typeGame=, score=0}]}, {teamId=2, scores=[{playerId=6, typeGame=, score=0}, {playerId=7, typeGame=, score=0}, {playerId=8, typeGame=, score=0}, {playerId=9, typeGame=, score=0}, {playerId=10, typeGame=, score=0}]}]}]
obj: {id=1, name=1-apr, teams=[{teamId=1, scores=[{playerId=1, typeGame=, score=0}, {playerId=2, typeGame=, score=0}, {playerId=3, typeGame=, score=0}, {playerId=4, typeGame=, score=0}, {playerId=5, typeGame=, score=0}]}, {teamId=2, scores=[{playerId=6, typeGame=, score=0}, {playerId=7, typeGame=, score=0}, {playerId=8, typeGame=, score=0}, {playerId=9, typeGame=, score=0}, {playerId=10, typeGame=, score=0}]}]}
obj: [{teamId=1, scores=[{playerId=1, typeGame=, score=0}, {playerId=2, typeGame=, score=0}, {playerId=3, typeGame=, score=0}, {playerId=4, typeGame=, score=0}, {playerId=5, typeGame=, score=0}]}, {teamId=2, scores=[{playerId=6, typeGame=, score=0}, {playerId=7, typeGame=, score=0}, {playerId=8, typeGame=, score=0}, {playerId=9, typeGame=, score=0}, {playerId=10, typeGame=, score=0}]}]
obj: {teamId=1, scores=[{playerId=1, typeGame=, score=0}, {playerId=2, typeGame=, score=0}, {playerId=3, typeGame=, score=0}, {playerId=4, typeGame=, score=0}, {playerId=5, typeGame=, score=0}]}
obj: [{playerId=1, typeGame=, score=0}, {playerId=2, typeGame=, score=0}, {playerId=3, typeGame=, score=0}, {playerId=4, typeGame=, score=0}, {playerId=5, typeGame=, score=0}]
obj: {playerId=1, typeGame=, score=0}
obj: {playerId=2, typeGame=, score=0}
obj: {playerId=3, typeGame=, score=0}
obj: {playerId=4, typeGame=, score=0}
obj: {playerId=5, typeGame=, score=0}
gameplayers map: (MyMap) {games/0/teams/0/scores/0/={playerId=1, typeGame=, score=0}}
An error occurred:
(Line: 878) 878
java.lang.ClassNotFoundException: java.lang.b4j.example.jsonpath
Maybe these log lines can give you an idea on how to proceed...
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
I definitely has something to do with how the JSONParser is behaving because if I replace it with this simple (incomplete) parser, everything works fine, also in release mode.

B4X:
private Sub MiniJsonParser(jsonStr As String) As Map
    Dim m As Map
    m.Initialize
    
    jsonStr = jsonStr.Trim
    jsonStr = jsonStr.SubString2(1, jsonStr.Length - 1)
    
    Dim keys() As String = Regex.Split(",", jsonStr)
    For i = 0 To keys.Length - 1
        Dim spl() As String = Regex.Split(":", keys(i))
        Dim key As String = RemoveOuterQuotes(spl(0))
        Dim tmpValue As String = RemoveOuterQuotes(spl(1))
        If IsNumber(tmpValue) Then
            Dim value As Long = tmpValue
            m.Put(key, value)
        Else
            m.Put(key, tmpValue)
        End If
    Next
    
    Return m
End Sub

private Sub RemoveOuterQuotes(str As String) As String
    If str.StartsWith(Chr(34)) And str.EndsWith(Chr(34)) Then
        Return str.SubString2(1, str.Length - 1)
    Else
        Return str
    End If
End Sub
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
Ok, found the little bugger. Sometimes 1 <> 1 (in my case, they are equal in debug mode but different in release mode). Tough one to spot...

Example:
B4X:
If tmpFilt <> Null And tmpFilt.IsInitialized Then
    For Each key2 As String In tmpFilt.Keys
        If m.ContainsKey(key2) = False Or m.Get(key2) <> tmpFilt.Get(key2) Then
            isSame = False
            Exit
        End If
    Next
End If

Has to become:

B4X:
If tmpFilt <> Null And tmpFilt.IsInitialized Then
    For Each key2 As String In tmpFilt.Keys
        If m.ContainsKey(key2) = False Then
            isSame = False
            Exit
        Else
            Dim v1 As String = m.Get(key2)
            Dim v2 As String = tmpFilt.Get(key2)
            If v1 <> v2 Then
                isSame = False
                Exit
            End If
        End If
    Next
End If

Still, no idea why it works in debug mode, but not in release mode
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
I see it. However it seems that in Addscore this line works both with and without the breakpoint in InnerFilter
Dim Players As Map = DB.Filter("teams/*/players", CreateMap("name" : PlayerName))
whereas this line doesn't
Dim GamePlayers As Map = DB.Filter($"games/{"id": 1}/teams/{"teamId": 1}/scores"$, CreateMap("playerId": PlayerIDl))

It looks like the path through InnerFilter is different for that input when the breakpoint is set but not for the other. So it doesn't seem to be an absolute problem with InnerFilter but is also input dependent. I doubt that it is a threading problem, I've looked inside JSONParser and its very straightforward simple Java just wrapping a native JSONTokener object.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
Well done! That's a bastard one to find. I don't really understand what is happening but it's one that Erel should definitely take a look at. Stuff like this is the reason I rarely use debug mode but normally go for Log and Msgbox debugging. Being as old as I am I was burnt by poor debuggers in the early days and now have a tendency to not really use them unless I really need to.
 
Upvote 0

teddybear

Well-Known Member
Licensed User
This issue is caused by the difference in types of the value between the two objects in sub GetInnerFilter.
m is from Object you defined it as Long, tmpFilt is from jsonP.NextObject, its value is int.
B4X:
Dim tvalue As Long=tmpFilt.Get(key2)
Dim mvalue As Long=m.Get(key2)
If m.ContainsKey(key2) = False Or mvalue <> tvalue Then
    isSame = False
    Exit
End If
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
You got it. It looks like it is the known effect of an If comparison that takes the type of the left most value to use in the comparison. It fails in normal use because it is comparing two object types, maybe doing an identity comparison rather than a value comparison, but if you force it to compare as Long it works. Why debug makes it work when it fails normally - who knows :rolleyes:
B4X:
If m.ContainsKey(key2) = False Or m.Get(key2).As(Long) <> tmpFilt.Get(key2) Then
    isSame = False
    Exit
End If
 
Upvote 0
Top