B4J Question [SOLVED]How to AutoReconnect to an MySQL server

Peter Lewis

Active Member
Licensed User
Longtime User
Hi all

I have a server app running which goes between my MySQL and MQTT. After around 24 hours I get this error.

I Tried to use Ctrl-M to copy the debug text and paste it but it just goes away as it sees it as a key press and I cannot select the text, so I had to do a screenshot. This after I compiled it and put it on the server machine and run in debug mode.
1588883216182.png

I have looked under all the options on the SQL init string and cannot find anywhere that allows me to re-connect.

If you know where I can set this parameter - Autoreconnect = true would be a great help

Thank you
 

Jorge M A

Well-Known Member
Licensed User
Try in connectionString
B4X:
Private driverClass As String="com.mysql.cj.jdbc.Driver"
  
Private connectionString As String="jdbc:mysql://{SERVER}:{PORT}/{DATABASE}?characterEncoding=utf8&autoReconnect=true&useTimezone=true&&serverTimezone=UTC&Pooling=True"
 
Upvote 0

Peter Lewis

Active Member
Licensed User
Longtime User
I cannot find any info on JconnectionPool that indicates that I can auto reconnect the connection.

I have tried with the JConnectionPool and used that to Init the database but and change all the Database reads but then there is no option for ExecQuery. Do I leave SQL along with JConnectionPool ?

I first searched for JConnectionPool on the forums and there was noting of how to set it up. I then looked under JServer to see the methodology but also could not get that.

B4X:
        Private sql2 As JdbcSQL
    Private CP As ConnectionPool
   
   
    If CP.IsInitialized = False Then    'in case the connection closes
        '  
        CP.Initialize("com.mysql.jdbc.Driver", "jdbc:mysql://192.168.1.103:3306/****_quiz", "user", "****")
   
    End If

Here is the problem

B4X:
rs=sql2.ExecQuery("SELECT name FROM Category")
    Do While rs.NextRow

If I change the SQL2 there to CP . And I do not see any parameters on the CP that will assist in keeping the connection alive

Thank you
 
Last edited:
Upvote 0

OliverA

Expert
Licensed User
Longtime User
B4X:
sql2 = CP.GetConnection
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Upvote 0

Peter Lewis

Active Member
Licensed User
Longtime User
No parameter needed. It’s one of the purposes of the connection pool. It’ll create a new connection if it needs too. This one is based on https://www.mchange.com/projects/c3p0/
Seems like it is not solved.

I put everything into the sever as you suggested and It crashes with this message

I closed all instances of sql at the end of each sub

but this still happens

Here is the code

B4X:
Case "Server/Advert"
       

           
            Dim arrNumString() As String =Regex.Split(",",PayLoadStr )
           
   
            Log("record to retrieve "&arrNumString(0))
            Dim Cursor As JdbcResultSet
           
            Dim adv As Int = arrNumString(0)
                           
                               
            If CP.IsInitialized = False Then    'in case the connection closes
                '
                CP.Initialize("com.mysql.jdbc.Driver", "jdbc:mysql://192.168.1.103:3306/***_quiz", "user", "********")
   
            End If

            sql2 = CP.GetConnection
           
           
           
            Cursor = sql2.ExecQuery2("SELECT AdNumber, WebsiteAddr FROM adverts where AdNumber =?", Array As String(adv))
            Do While Cursor.NextRow
                Log("about to get")
                Dim sendstr As String =Cursor.GetString("WebsiteAddr")
               
                Log(sendstr)
                PostThis2(arrNumString(1)&"/Adverts",sendstr,2,False)
            Loop
            sql2.Close
Cursor.close
 
Upvote 0

Peter Lewis

Active Member
Licensed User
Longtime User
1. ResultSet should be a local variable.
2. SQL should be a local variable.
3. You should close the ResultSet before you close the connection.

When does the error happen? Immediately?

Thank you for your reply

1. the resultset was a local Variable on line 9 of the posted code
2. SQL was in the process globals of that Module, I have now changed it to inside the Sub
3. I have changed the resultset close to before the Sql Close

No the error did not happen immediately. I had to start the game, play the game and in the result is where the error came up, Immediately.

The same function that crashed, was working perfectly during the game and was used in the game to display adverts. The request for advert in the result module is exactly the same as the play Game Module.

I also added another close after the sql.close and that is cp.Closepool

I expect the the order is correct as SQL assignment was after Connection Pool was created

This is now the complete sub with all the other functions.

Please excuse the untidiness of the code.

B4X:
Public Sub Client1_MessageArrived (Topic As String, Payload() As Byte)
    Dim cp As ConnectionPool
    Dim sql2 As JdbcSQL
    
    
    ' Initialize Bothe rConnection pool and SQL
    
    If cp.IsInitialized = False Then    'in case the connection closes
    
        cp.Initialize("com.mysql.jdbc.Driver", "jdbc:mysql://192.168.1.103:3306/*****_quiz", "user", "**********")
    
    End If

    sql2 = cp.GetConnection

    
    Dim PayLoadStr As String
    Log("Message Arrived")
    Log("Message Topic "&Topic)
    Log(Payload.Length)

    PayLoadStr = BytesToString(Payload, 0, Payload.Length, "utf8")
    Log(Topic & " = " & PayLoadStr)
    
    If PayLoadStr.Length = 0 Then
        Return
    End If
    
    Dim paytopic As String
    paytopic=Topic.Trim

    Log("This should be right "&paytopic)

    Select Topic
        Case "Server"  'Received the initial Logingname of the user to create a perm topic retained
            Main.LIncomingMessage.Text=Topic&" "&PayLoadStr
            
            If PayLoadStr <> "" Then
                Subscribe2(PayLoadStr.Trim&"/Register",2)
                
            Main.Member=PayLoadStr.Trim
            Main.UpdateCat
            Main.UpdateSubCat
                
            End If
            
            
        Case "Server/Adinfo" ' Saves When the Advert Was displayed as well as the user and the duration
            
    
            Dim arrNumString() As String =Regex.Split(",",PayLoadStr )
            sql2.ExecNonQuery2("INSERT INTO advertinfo VALUES (?,?,?,?)", Array As Object(arrNumString(0),arrNumString(1),arrNumString(2),arrNumString(3)))
      
      
            sql2.Close
            cp.ClosePool
            
        Case "Server/Advert" 'Sends the Advert Website Address
        

                Dim arrNumString() As String =Regex.Split(",",PayLoadStr )
                        Log("record to retrieve "&arrNumString(0))
            
            
            Dim adv As Int = arrNumString(0)
                            
            Dim Cursor As JdbcResultSet
            Cursor = sql2.ExecQuery2("SELECT AdNumber, WebsiteAddr FROM adverts where AdNumber =?", Array As String(adv))
            Do While Cursor.NextRow
                Log("about to get Ad")
                Dim sendstr As String =Cursor.GetString("WebsiteAddr")
                
                Log(sendstr)
                PostThis2(arrNumString(1)&"/Adverts",sendstr,2,False)
            Loop
            
            Cursor.Close
            sql2.Close
            cp.ClosePool
            
        Case "Server/Reg"  ' Registers a player on the system
            Log("Received reg message")
            Log(PayLoadStr.Trim)
                
            sql2 = cp.GetConnection
    
            Dim arrNumString() As String =Regex.Split(",",PayLoadStr )
        
                  
            sql2.ExecNonQuery2("INSERT INTO user_db VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)", Array As Object(arrNumString(12),arrNumString(0), arrNumString(1), arrNumString(2), arrNumString(3), arrNumString(4), arrNumString(5), arrNumString(6), arrNumString(7), arrNumString(8), arrNumString(9), arrNumString(10), arrNumString(11)))
      
            Log("past insert local")
            sql2.Close
            cp.ClosePool
                        
    End Select
    
    DateTime.SetTimeZone(2)

    
End Sub

THANK YOU
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Do not close you pool!!! That’s the whole point of a pool. Your pool is a global variable and should be initialized once on program start. You are getting sql2 way before you use it: don’t do that! Get a pool connection just before getting your result set. Once done with the set, close it and the sql2 (unless you do several calls in a row, at that time feel free to use the same sql2 connection). Checking to see if the pool is initialized should not be necessary, since you should do that at program start. One pool for all your connection requests. One connection per request (unless the requests are back to back). Close result sets when done. Close connection (not pool) after closing result set (if there is one). Do not close pool.
 
Upvote 0

Peter Lewis

Active Member
Licensed User
Longtime User
Do not close you pool!!! That’s the whole point of a pool. Your pool is a global variable and should be initialized once on program start. You are getting sql2 way before you use it: don’t do that! Get a pool connection just before getting your result set. Once done with the set, close it and the sql2 (unless you do several calls in a row, at that time feel free to use the same sql2 connection). Checking to see if the pool is initialized should not be necessary, since you should do that at program start. One pool for all your connection requests. One connection per request (unless the requests are back to back). Close result sets when done. Close connection (not pool) after closing result set (if there is one). Do not close pool.
I also thought that might be an overkill . Please understand that this sub will be serving 100's or 1000's of users at anytime. I was thinking that maybe i should use Threading for this , so I expect I will have to change the routine anyway. I have 3 different server programs that work between the MQTT servers(2 of them) and the SQL database. I have tried to spread the load between the 3 server programs but I think that Threading will be the answer.

I will take out the CP closepool on all of them and will let you know

Thank you for the advice
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
I have 3 different server programs that work between the MQTT servers(2 of them) and the SQL database.
You should not need this many servers for 100’s to 1000’s of users
 
Upvote 0

Peter Lewis

Active Member
Licensed User
Longtime User
Do not close you pool!!! That’s the whole point of a pool. Your pool is a global variable and should be initialized once on program start. You are getting sql2 way before you use it: don’t do that! Get a pool connection just before getting your result set. Once done with the set, close it and the sql2 (unless you do several calls in a row, at that time feel free to use the same sql2 connection). Checking to see if the pool is initialized should not be necessary, since you should do that at program start. One pool for all your connection requests. One connection per request (unless the requests are back to back). Close result sets when done. Close connection (not pool) after closing result set (if there is one). Do not close pool.
Hi

I did what you suggested and I found it crashed after 25 loops on the 26th one it crashes, I tested it twice. If I left the close.closePool it did not crash. here is the fresh message


Should i not be increasing the pool size. I saw someone on a post said put it to 100 and their one did not crash ?

How do you change one of those parameters ie poolsize ?

Thank you
 
Last edited:
Upvote 0

OliverA

Expert
Licensed User
Longtime User
You may need to tweak the pool. maxPoolSize is set to 15. You may need to up that. Do not close the pool. If you persist on using pools in a manner that is not how they should be used, it will be very hard for you to get help on this forum. Pools are a technology onto themselves, and some knowledge about them is needed to use them. It could also mean that you may want to switch to a different pool. But before doing that, you should really understand the usage of pools and some of the tweaks that can be done to pools to help you implement them properly.

Here is the same issue: https://www.b4x.com/android/forum/t...m-connection-has-timed-out.95067/#post-600975
If you read the thread, @Harris provides the code to enlarge the pool size. You do not have to copy 100% of his code, the relevant portion is
B4X:
    ' change pool size...
    Dim jo As JavaObject = pool
    jo.RunMethod("setMaxPoolSize", Array(poolSize))

This needs to be called just after you initialize the pool. Replace poolSize with a size or just create a variable poolSize with a size to use the code above.

There are other threads on this forum about pool options. If you really feel comfortable about what you are doing and you think the current pool manager is not right for your project, there are other threads here about using another pool manager as an option. This should only be done if you understand pools and if you understand how to implement the other pool manager.

Update: In your case, the above code should use CP instead of pool so
B4X:
    ' change pool size...
    Dim jo As JavaObject = CP
    jo.RunMethod("setMaxPoolSize", Array(poolSize))
 
Upvote 0

Peter Lewis

Active Member
Licensed User
Longtime User
You may need to tweak the pool. maxPoolSize is set to 15. You may need to up that. Do not close the pool. If you persist on using pools in a manner that is not how they should be used, it will be very hard for you to get help on this forum. Pools are a technology onto themselves, and some knowledge about them is needed to use them. It could also mean that you may want to switch to a different pool. But before doing that, you should really understand the usage of pools and some of the tweaks that can be done to pools to help you implement them properly.

Here is the same issue: https://www.b4x.com/android/forum/t...m-connection-has-timed-out.95067/#post-600975
If you read the thread, @Harris provides the code to enlarge the pool size. You do not have to copy 100% of his code, the relevant portion is
B4X:
    ' change pool size...
    Dim jo As JavaObject = pool
    jo.RunMethod("setMaxPoolSize", Array(poolSize))

This needs to be called just after you initialize the pool. Replace poolSize with a size or just create a variable poolSize with a size to use the code above.

There are other threads on this forum about pool options. If you really feel comfortable about what you are doing and you think the current pool manager is not right for your project, there are other threads here about using another pool manager as an option. This should only be done if you understand pools and if you understand how to implement the other pool manager.

Update: In your case, the above code should use CP instead of pool so
B4X:
    ' change pool size...
    Dim jo As JavaObject = CP
    jo.RunMethod("setMaxPoolSize", Array(poolSize))
I will try this now.

Thank you for taking the time to give a well thought out answer, I appreciate it
 
Upvote 0

Peter Lewis

Active Member
Licensed User
Longtime User
I tried increasing the pool size to 100 but still had the crashing on 2 of the 3 server programs. The third program I have left it as the initial init without the Connection pool

Here are the error screens


Do you think that maybe the MySQL server is banning me after 25 connections ?

Thank you
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
You may be clobbering your SQL server. Why don't you try with one pool running (not 2 or 3). Where is your SQL server located in relation to the the solution you are creating here?
 
Upvote 0

Peter Lewis

Active Member
Licensed User
Longtime User
You may be clobbering your SQL server. Why don't you try with one pool running (not 2 or 3). Where is your SQL server located in relation to the the solution you are creating here?
My server in in my Lounge running WMWare Dual Zeons with 128GB RAM, each of my VMs are using both CPU's and 32Gb RAM
(Too loud for running in my dev room)
So I should change the connection pool to 1

Thank you
 
Last edited:
Upvote 0
Top