B4J Question B4J Server returning a list or map

Discussion in 'B4J Questions' started by Tadeu Botelho, Mar 17, 2018.

  1. Tadeu Botelho

    Tadeu Botelho Member Licensed User

    I'm working on server development by following the following example:
    https://www.b4x.com/android/forum/t...device-desktop-and-web-reports.37254/#content
    I need to return a list with data from a table:
    ID, Name, Age, Email
    With their respective data.
    This list needs to be sent to a B4J application that is loading its data into a TableViewer.
    Is there any example with these codes? Because I did not find anything like this:
    '// B4J Server:
    Code:
    Sub Handle(req As ServletRequest, resp As ServletResponse)
     
    Dim resp As Map = DBUtils.ExecuteMap(Main.SQL, "SELECT * FROM Animals")
     resp.ContentType = 
    "Map" '// Map ? '// how to set a list or map to client?
     resp.Write(resp)
    End Sub
    '// B4J Client:
    Code:
    Sub Process_Globals
     
    Private fx   As JFX
     
    Private MainForm  As Form
     
    Private TableView  As TableView 
     
    Private raf   As RandomAccessFile
     
    Private link   As String 
    End Sub
    Sub AppStart (Form1 As Form, Args() As String)
     MainForm = Form1
     MainForm.Show
     raf.Initialize(
    File.DirTemp, "temp"False)
     MainForm.Title = 
    "Tabela {Pessoas} em http://IP:porta em {BdServidor.db}"
    End Sub
    Sub btnDadosExibirNoTableView_Action
     link = 
    "http://localhost:51042"
     
    Dim j As HttpJob
     j.Initialize(
    "report2", Me) 
     j.Download(link & 
    "/Relatorio2")
     pi1.Visible = 
    True
    End Sub
    Sub JobDone(j As HttpJob
     
    If j.Success Then
      
    If j.JobName = "report2" Then
       
    '// how to get a list or map in a tableview?
       TableView.Items.AddAllAt( j.GetString2("  Map????  ") )
      
    End if
     
    End If
    End Sub
    I will be very grateful for the help
     
  2. OliverA

    OliverA Well-Known Member Licensed User

    1) You may want to look into JRDC2 (https://www.b4x.com/android/forum/t...-rdc-remote-database-connector.61801/#content) for retrieving information from a database. There are a couple of modified versions here in the forum that may be of interest:

    a) Modded jRDC2 w/SQLite support and more (https://www.b4x.com/android/forum/threads/modded-jrdc2-w-sqlite-support-and-more.85578/). This one out of the box uses SQLite and is therefore a little bit easier to set up. One of the commenters ( @inakigarm ) mentioned he had a modification that would allow for dynamically updating SQL statements (https://www.b4x.com/android/forum/threads/modded-jrdc2-w-sqlite-support-and-more.85578/#post-542226). There is a companion B4J client example (https://www.b4x.com/android/forum/threads/jrdc2-client-example-using-modded-jrdc2.85581/#content) that is a modified version of the DBUtils example. That example should also run against the original JRDC2 (Disclaimer: this is my mod).

    b) Another customized version of JRDC2 by @tigrot (https://www.b4x.com/android/forum/threads/another-customised-version-of-jrdc2.72082/#content) adds file up/download capabilities and ad-hoc SQL queries.

    c) jRDC Hikari mix by @MichalK73 (https://www.b4x.com/android/forum/threads/jrdc-hikari-mix.90033/#post-569115) changes the database pool used, adds method calls, some security and dynamic loading of methods/SQL queries, etc.​

    2) If you insist on doing things your own way, then

    on the server side you'll need something like this (BTW, you mentioned list, but are using a map, so I'm sticking with a map):

    Code:
    Dim m as Map
    'Code that fills the map here
    '.
    'Code to serialize map and transfer to client
    Dim ser as B4XSerializator
    Dim data() as Byte = ser.ConvertObjectToBytes(m)
    resp.OutputStream.WriteBytes(data, 
    0, data.Length)
    on the client side:

    Code:
    'This is the code used instead of plain Job.GetString method
    Dim ser as B4XSerializator
    Dim data() as Byte = Bit.InputStreamToBytes(Job.GetInputStream)
    Dim m As Map = ser.ConvertBytesToObject(data)
    Note: Code not tested, just adopted from JRDC2/DBRequestManager source of original JRDC2. Adjust any variable names as necessary.
     
  3. KMatle

    KMatle Expert Licensed User

    I use asyncstreams for smaller inhouse solutions. You can easily handle e.g. users, permissions and connections.
     
    inakigarm and OliverA like this.
  4. Tadeu Botelho

    Tadeu Botelho Member Licensed User

    Thanks a lot for the help!
    Now it's possible to solve the problem by creating custom object types :)
     
  5. XbNnX_507

    XbNnX_507 Active Member Licensed User

    Another option would be to send a Json string intsead of Map.

    Server Side.
    Client Side
     
    Tadeu Botelho likes this.
  6. OliverA

    OliverA Well-Known Member Licensed User

    Tadeu Botelho likes this.
  7. schimanski

    schimanski Well-Known Member Licensed User

    Is there any difference in the performance when using B4XSerializator or JSON?
     
  8. XbNnX_507

    XbNnX_507 Active Member Licensed User

    if you are implementing server side code and client side code in B4X then i think is best to use B4Xserializator.
    if you have no control over the client side code then i think JSon is a better option given the fact the B4XSerializator is a unique B4J B4A feature.
    i Don't think there's a performance difference maybe Erel could answer that.
     
    Tadeu Botelho, OliverA and schimanski like this.
  9. KMatle

    KMatle Expert Licensed User

    I work with lists with maps converted to Json strings. As I encrypt everythng the result are bytes which then can be sent via asyncstreams. On bigger environments I use Apache with php and OkHttputils. I convert the bytes to a Base64 string. Big advantage: It's always the same procedure in all environments.

    No need for custom types. Lists and maps are just arrays. When converted to a Json structure all plattforms can handle it.
     
  10. Tadeu Botelho

    Tadeu Botelho Member Licensed User

    Is there a difference in performance when opting for this procedure?
     
  11. keirS

    keirS Well-Known Member Licensed User

    A Map is not an array.
     
  12. Tadeu Botelho

    Tadeu Botelho Member Licensed User

    Your response was very helpful. Thank you!
    I'm creating a server that will be consumed by clients that do not have access to source code. So the returns to those clients would be via JSON.
    But most of the returns will be for systems made by me through the B4J Client.JAR and B4A Client.APK
    So in this second situation I will work with the B4XSerializator because of the custom types. That in my case, I really enjoy working with them.
    My only doubt is still only in performance between the two.
    But so far my development with the B4X Platform is thriving.
    I loved these magnificent B4X tools.
     
    XbNnX_507 likes this.
  13. KMatle

    KMatle Expert Licensed User

    This is correct. What I meant: If you convert a list/map structure to JSON and send it to php, they can be handled in php like arrays after decoding. The point is: This is compatible with all platforms. The serializator is a B4x thing. So I only use lists/maps encoded to a JSON string in all of my apps. One concept fits it all.
     
    Tadeu Botelho and LucaMs like this.
  14. schimanski

    schimanski Well-Known Member Licensed User

    To the lot of experts here in the thread, I still have one question:

    I use such server-handler with the code above:

    Code:
    Sub Handle(req As ServletRequest, resp As ServletResponse)
     
        
    Dim NTask As NTask = serializator.ConvertBytesToObject(Bit.InputStreamToBytes(req.InputStream))
     
        
    If NTask.NTaskName="getdata" Then
            
    Dim bytes() As Byte = serializator.ConvertObjectToBytes(NachrichtenSyncDB.Get(req.GetParameter("absender")))
            resp.OutputStream.WriteBytes(bytes, 
    0, bytes.Length)
        
    Else
            
    If NTask.NTaskName="putdata" Then
               ...
               NachrichtenSyncDB.Put(req.GetParameter(
    "absender"),  NTask.NTaskItem)
               ....
    Only the server writes to it and the clients only reads over the handler. Do I have to use now a code-modul with the following code like cloudkvs does:

    Code:
    Public Sub Put(Key As String, Value As Object)
        
    lock.WriteLock
        
    Try
            
    Private ser As B4XSerializator
            
    sql.ExecNonQuery2("INSERT OR REPLACE INTO " & Standort & " VALUES(?, ?)"Array As Object(Key, ser.ConvertObjectToBytes(Value)))
        
    Catch
            
    Log(LastException)
        
    End Try
        
    lock.WriteRelease
    End Sub
    or is it better to use a class-modul like keyvaluestore2 with this code:

    Code:
    Public Sub Put(Key As String, Value As Object)
        
    Private ser As B4XSerializator
        sql1.ExecNonQuery2(
    "INSERT OR REPLACE INTO main VALUES(?, ?)"Array As Object(Key, ser.ConvertObjectToBytes(Value)))
    End Sub
     
    Last edited: Mar 20, 2018
  15. OliverA

    OliverA Well-Known Member Licensed User

    The Put method for CloudKVS that you are showing is part of the client portion. The client has no code module, it's a class module.

    Read this article (https://msdn.microsoft.com/en-us/library/aa733572(v=vs.60).aspx) by Microsoft, where standard module is equivalent to code module.

    Then look at the CloudKVS server where the same database is used for all access. In this case, each request gets a new handler, but each handler talks to the same database. In this case, a code module for the database portion makes sense. But, it could have been a class. That's actually how JRDC2 does it (and out of the box it only serves one database). In short, it's up to you.

    As to KVS2, by making it a class module, you can actually have more than one KVS2 storage used per application. If it were a code module, you would restrict the application to only have one KVS2 store. BTW, since the CloudKVS client is a class module, your client application is not restricted to talking to only one CloudKVS server.

    Hope I made it clear as mud.
     
    Tadeu Botelho and schimanski like this.
  16. schimanski

    schimanski Well-Known Member Licensed User

    Thanks for your efforts, OliverA. Your explanations are very useful. I decided to use a code module for the database portion like cloudkvs does!
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice