B4J Tutorial jRDC2 client example (using modded jRDC2)

Attached you find an example of accessing a jRDC2 server. This is a conversion of the DBUtils example program (here: https://www.b4x.com/android/forum/threads/dbutils-example.34611/#content). Please use the modded jRDC2 server (here: https://www.b4x.com/android/forum/threads/modded-jrdc2-w-sqlite-support-and-more.85578/). I used this client to do some "smoke" testing and remove some uncaught exceptions errors that I triggered in the original jRDC2 code (here: https://www.b4x.com/android/forum/t...ation-of-rdc-remote-database-connector.61801/). Please note that I create a "helper" code module jRDC2Utils that encapsulates some of the jRDC2 communication. This may not be the way to go, but it seems to work. I do seem to have some issues with events and order of events (one is documented in the source, the end of the AppStart method). For now it shows a small glimpse of jRDC2.

2018/05/29 Update: Fixed a race condition in cmbStudentID_ValueChanged. Tried three options (see code) and picked third one. Thanks once more to @Diceman for pointing it out and making me look at it more closely. (https://www.b4x.com/android/forum/threads/jrdc2-client-example-using-modded-jrdc2.85581/#post-588834)

2018/05/16 Update: Updated client application to use newer bjl layout file instead of older fxml format. Thanks to @Diceman for pointing out the issue. (https://www.b4x.com/android/forum/threads/jrdc2-client-example-using-modded-jrdc2.85581/#post-591798)
 

Attachments

  • jRDCv2_Client_B4J.zip
    9.2 KB · Views: 1,152
Last edited:

Diceman

Active Member
Licensed User
I downloaded your zip file and loaded it using B4J v6.01.
When I ran the Designer I get an out of memory error. This hasn't happened before with any other project. Can you check the form to see if has been corrupted?
(I downloaded the file twice and I get the out of memory error each time.) jRDC2v2_Client_B4j_Designer_Bug.png

TIA
 

OliverA

Expert
Licensed User
Longtime User
This error happens when you try to load an old FXML layout file with the internal designer.
Yeah that's because I'm not that great with UI designs and was just using what was given with the DBUtils example that I found.
Can you check the form to see if has been corrupted?
I'll take a look at it and see if I can recreate the UI to make it work with a more up to date B4J.
This example is not based on the latest version of jRDC2.
True, but I think the only thing that is missing of the modded JRDC is the datetime capability.
It doesn't use the recommended approach which is explained in the tutorial.
Huh? I'm using wait for and I create a new DBRequestManager for each request. I just wrap this up in some helper methods. What's wrong with that? I'm just asking, since if I'm doing something wrong on the JRDC side, I need to fix it.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Huh? I'm using wait for and I create a new DBRequestManager for each request. I just wrap this up in some helper methods. What's wrong with that? I'm just asking, since if I'm doing something wrong on the JRDC side, I need to fix it.
My mistake. Sorry. I took a quick look and thought that it is based on an older version of jRDC2 (most examples with FXML layouts are very old).
 

OliverA

Expert
Licensed User
Longtime User
When I ran the Designer I get an out of memory error.
This error happens when you try to load an old FXML layout file with the internal designer.
Fixed. Download file in post#1 has been updated. Note that this update only affects the layout file. No new functionality has been added.
 

Diceman

Active Member
Licensed User
The new design layout loads fine now, thanks.

I did notice if I run the client app and select a row in TableView1 and keep holding down the down arrow key, the program goes into an infinite loop with a lot of scrolling even after the down arrow key is released. Same thing if I'm at the bottom of the list and hold down the up arrow key.

It appears the problem is related to cmbStudentID_ValueChanged where it calls TableView1.ScrollTo which causes cmbTests_SelectedIndexChanged or TableView1_SelectedRowChanged to be called. There needs to be a flag set to prevent the events from repetitively calling each other.

This error may be in Erel's original code, I don't know because I don't have MySQL installed so I could not try it.
It is not a huge problem since it doesn't deter from the calls to the server. It is just annoying because the only way to stop it is to terminate the client.

On a more positive note, it does show the jRDC2 server can handle a barrage of these requests without slowing down. :)
 

OliverA

Expert
Licensed User
Longtime User
It appears the problem is related to cmbStudentID_ValueChanged where it calls TableView1.ScrollTo which causes cmbTests_SelectedIndexChanged or TableView1_SelectedRowChanged to be called.
This error may be in Erel's original code, I don't know because I don't have MySQL installed so I could not try it.
I've noticed this while redoing the layout file, but did not spent any more time on it. Since you are experiencing this issue too, I may take another look at it. This may be due to the usage of Wait For. Event handling needs to be managed a bit different, since Wait For allows for the processing of the event queue and therefore may lead to such event handling. If you look at the code, the last part of AppStart has a note about events firing differently than the original DBUtils program and I'm surmising it is due to Wait For. I think this is another case (and this issue does not surface in the original code). Please note that I'm not saying that there is anything wrong with Wait For, but that event handling may need to be handled differently in certain situations with Wait For.
 

Diceman

Active Member
Licensed User
I believe the problem only occurs when the TableView1.ScrollTo statement is executed to reposition the top of the tableview so the selected row is visible. If you simply use the down arrow to move to a row that is already visible, it works fine. I added some flags to prevent other view events from being executed if another event is processing the changes. It seems to work. (It's not pretty nor thoroughly tested which is why I didn't post it here.) But if you concentrate on the TableView1.ScrollTo event, I think it is the origin of the infinite loop.
 

OliverA

Expert
Licensed User
Longtime User
But if you concentrate on the TableView1.ScrollTo event, I think it is the origin of the infinite loop.
The issue is actually cmbStudentID_ValueChanged. The offending line is the following
B4X:
If TableView1.SelectedRow = -1 Or TableView1.SelectedRowValues(0) <> Value Then
Here is how it plays out:
1) Push down arrow
2) TableView1_SelectedRowChanged is called
a) cmbStudendID.Value is changed (if Index is not -1) and triggers the ValueChanged event
3) cmbStudentID_ValueChanged is called with the new value given in step #2. For our purposes, it is ID#2
a) A Wait For is used to load the student information given the value passed on to cmbStudentID_ValueChanged (ID#3)
*** This is the part the causes the issue. The Wait For allows for the processing of new events/queued events (therefor making the UI responsive).
4) Before 3a finishes, another down arrow is pressed which causes another ValueChanged event to fire
5) cmbStudentID_ValueChanged is called with the new value given in step #2. For our purposes, it is ID#3
a) A Wait For is used to load the student information given the value passed on to cmbStudentID_ValueChanged (ID#3)
3) continues
b) Wait For "select_tests"
5) continues
b) Wait For "select_tests"
3) continues
c) Wait For FindFailedTests
5) continues
c) Wait For FindFailedTests
3) continues - Here is where it all falls down
d)
B4X:
If TableView1.SelectedRow = -1 Or TableView1.SelectedRowValues(0) <> Value Then
If you use the cursor keys or click on a record with the mouse, SelectedRowValues(0) should be the same as Value and everything should just work as is (the IF statement block should be skipped). But, because Wait For allowed for processing of events and because of #4, the following happens:
SelectedRowValues(0) = ID#3 (the highlighted record) and not equal to ID#2 (as passed to Step 3 of the cmbStudentID_ValueChanged call). Therefore, we process the if statement which changes the SelectedRowValues to those of the row ID#2 and changes the highlight back to the TableView1 item with the ID#2 using ScrollTo, triggering an event for
6) TableView1_SelectedRowChanged is called
a) cmbStudendID.Value is changed (if Index is not -1) and triggers the ValueChanged event. The value is ID#2
5) continues - let's start some looping
d)
B4X:
If TableView1.SelectedRow = -1 Or TableView1.SelectedRowValues(0) <> Value Then
Because of 3d), SelectedRowValues(0) is ID#2, which is not equal to ID#3. Therefore we process the IF statement, changing SelectedRowValues to those of row id#3. ScrollTo is called to change the highlight back to the TableView1 item with ID#3, triggering an event for
7) TableView1_SelectedRowChanged is called
a) cmbStudendID.Value is changed (if Index is not -1) and triggers the ValueChanged event. The value id ID#3
8) a) Repeat 3a
9) a) Repeat 5a
8) b) Repeat 3b
9) b) Repeat 5b
etc...

Casually using the up and down arrow keys does not trigger this, but holding down the arrow keys (either up or down) will and it does not matter if you are hitting the beginning or the end. And it is usually a little bit more complicated since the rapid key presses allowes for 3,4,or 5 differend ID's to bounce back and forth between each other. What a mess.

2 solutions that I tried that did not solve the issue (before realizing exactly what is happening):
1) Using a busyFlag (did not solve the issue)
2) Enabling/Disabling the TableView (bad).

The final solution that worked:
Before calling the first Wait For in the cmbStudentID_ValueChanged method do
B4X:
Dim selectedRow As Int = TableView1.SelectedRow
Dim selectedRowValue As Object = TableView1.SelectedRowValues(0)
and change the IF statement to
B4X:
If selectedRow = -1 Or selectedRowValue <> Value Then
This way we isolate the method from changes to the underlying TableView1 class that can happen by events that happen during Wait For and can properly process (in this case, skip processing) the table record highlighting.

Updated code attached in Post#1
P.S.: Hope this made some sense
 

Diceman

Active Member
Licensed User
Your solution has solved the infinite loop problem. It works much better now.
Thanks. ;)
 
Top