B4J Question [BANanoServer] [SOLVED] How to fix the SHARED cannot set property 'length' of null

Mashiane

Expert
Licensed User
Longtime User
Ola

This is my definition of my SHARED...

B4X:
#Region BANano 
    ' <-------------- IMPORTANT! This is because we want the non specific B4J code in this module to be transpiled by BANano
#End Region

Sub Class_Globals
    Private BANano As BANano   'ignore
    Public OK As Boolean
    Public DBase As String
    Public result As List
    Public command As String
    Public types As List
    Public args As List
    Public query As String
    Public response As String
    Public error As String
    Public affectedRows As Long
    Public payload As String
    Private usePool As Boolean
    Public lastID As Long
    Public view As String
    Public action As String
    #if b4j
    Private jSQL As SQL
    Private pool As ConnectionPool
    #end if
End Sub

My initialize call is like this..

B4X:
Sub Initialize(pl As String)
    Log("SHAREDDoc.Initialize")
    'Try
    result.Initialize
    command = ""
    DBase = ""
    types.Initialize
    args.Initialize
    types = Null
    args = Null
    query = ""
    response = ""
    error = ""
    affectedRows = 0
    payload = ""
    OK = False
    usePool = False
    lastID = 0
    view = ""
    action = ""
    'Catch
    '    Log(LastException)
    'End Try    
    If pl <> "" Then
        payload = pl
        FromJSON(payload)
    End If
End Sub

The intention is to pass the initialize sub a payload which will be converted to a map only if its available.

The SERVER call for this works exceptionally well and I don't have issues as I am able to pass it a payload, it processes it without issues. This is made via a promise call to this method

B4X:
Sub SQLOnServer(payload As String) As String
    Log("ServerIndex.SQLOnServer...")
    odbc.Initialize(payload)
    odbc.OpenSQL
    odbc.ToJSON
    odbc.CloseSQL
    Return odbc.payload
End Sub

This receives a payload, converts it into a map and assign values to the SHARED variables as defined in CLASS GLOBALS above.

The problem starts when calling SHARED Initialize from the BROWSER, I'm getting a cannot set property 'length' of null.



This error happens during this call, its like the variables and their types no longer exist. Perhaps I'm doing this the wrong way.

B4X:
Dim resp As String
    Dim prom As BANanoPromise = ws.RunFunctionWithResult("SQLOnServer", Array(jsonPayload))
    BANano.Await(prom)
    prom.Then(resp)
        Log("payload received...")
        Log(resp)
        
        odbc.Initialize(resp)
        Log(odbc)

Thanks.
 

alwaysbusy

Expert
Licensed User
Longtime User
A bit difficult to tell from what I see. Maybe this condition failes: If pl <> "" Then and it is something (even undefined or null) so FromJson() is executed?

Click in the Browser log on browserindex.js:16183 and look in the console at the JavaScript on which command it actually fails. It may give you a clue.

Also, the BANano.Await looks like a weird construction to me (I don't think this will solve your issue, just a general tip).

Either do:
B4X:
Dim resp As String
Dim prom As BANanoPromise = ws.RunFunctionWithResult("SQLOnServer", Array(jsonPayload))
resp = BANano.Await(prom) ' code waits here, bit like a B4J Resumable Sub
' this code will not be executed until prom has been resolved
log("And now this...")

or:
B4X:
Dim resp As String
Dim prom As BANanoPromise = ws.RunFunctionWithResult("SQLOnServer", Array(jsonPayload))
prom.Then(resp)
     ' this code is executed when prom is resolved
     ...
prom.end

' this code will not wait until prom has been resolved
log("And now this...")

Two different code flows. The second one has the advantage it can catch errors with the .Else().

Alwaysbusy
 
Upvote 0

Harris

Expert
Licensed User
Longtime User
You know, it is always difficult to tell - BUT - it is forever up to those to post relevant questions....

In this example, it "seems" that a question was posted prematurely before thoroughly examining their issue.

A responder took their (valuable) time to examine the question and provide an educated response - weather or not it was on point (relevant) ...

I see where this comes from - based on these easy choices:

a) post a question - and move on to other code - easy...
b) struggle with issue - and try to resolve... THEN post a question - examine response
c) No response.... - figure it out by studying your code. (hard)

Sometimes, we have to make hard choices...

I understand that many of us on on a time schedule to produce.
However, that is no excuse to expect others to (suggest a) resolve your issue - when you figure you don't have time to resolve it yourself - after your proper examination.

Many of us read these posts. We want to help, but not all of us have the time to suck away from our own to research and help resolve your post.

This should be a forum rule.... How to apply it? - it's just code...
 
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
LOL. @Harris, you probably woke up on the wrong side of the bed today hey. Take it easy man! I wish you didn't have to pollute this thread.

Personally this BROWSER, SERVER, SHARED issue of the BANanoServer can be confusing for new people like me. BTW, have you ever used it by any chance?

Thanks again @alwaysbusy for your help and advise, its always valuable.

Ta!
 
Last edited:
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
I think it is a 'general' point Harris is making, irrelevant if he uses BANano/BANanoServer or not. No idea what is confusing for you about SERVER, BROWSER and SHARED (see https://www.b4x.com/android/forum/t...ananoserver-going-full-circle.111406/#content) but in short:

SERVER: will be transpiled by B4J to Java (can use everything a normal B4J app can do, including all B4J libraries)
BROWSER: will be transpiled by BANano to JavaScript (can use only BANano compatible code, BANanoLibraries but no other B4J libraries)
SHARED: will be transpiled by B4J to Java AND by BANano to JavaScript (same rules as BROWSER, except you can use #if B4J for specific B4J code, skipped by BANano)

Communication between de Server and Browser is done with WebSockets (so bidirectional)
SERVER -> BROWSER: Normal B4J Future and ws.RunFunctionWithResult
BROWSER -> SERVER: BANanoPromise and ws.RunFunctionWithResult

That is it! Really, there is nothing more to it. For the SERVER side, Erel made plenty of tutorials and for the BROWSER (BANano) side, you wrote many yourself. So don't sell yourself short, if you understand the above six lines, you got it!

This aside, the biggest problem here for me was just not having enough info (tiny snippets are most of the time worthless to find errors, as there are numerous ways beyond it that can cause the problem). Proven in point here that the real problem was in some other code, not shown in your snippets (If args <> null then does not appear anywhere in the code shown).

As it turned out, the error had nothing to do with BANanoServer nor with BANanoPromise, but with some difference between how Java and JavaScript handle Nulls. (Maybe avoid using it, as in JavaScript it can indeed give unexpected results, especially when doing compares with it. In some cases, undefined can be equal to null, so go figure).

I agree that the error giving by the browser here is bit puzzling as it mentions Promise, however the key in that error message was that one asks for the length of something that is null. Missing the relevant code, I wrongly assumed FromJson() was executed (most likely to ask for something like .length).

Just saying that giving an example where one can reproduce the problem helps enormous and, as Harris points out, is less frustrating (and more time consuming) for those who want to help. And I'm sure you prefer that too if someone reports a problem in one of your libs

Alwaysbusy
 
Last edited:
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
Ola

Perhaps for a little bit of a background, any my apologies for not being clear enough.

In my BANano implementations, I am using the same .Initialize statement with args=null and types=null. This has been working in all the cases of backend database implementations. The classes build the arguement values for the CallInlinePHP call.

So the exercise for me has been to port my already hassle free code to the BANanoServer context so that I can database. So boom, the code does not work.

Your previous answer made me think exactly this...

So whilst the code has been working before without hustles with BANano, my logic was still saying, its probably something else. Imagine me trying to convince myself that BANano works, so BANanoServer should work. It works, however not in this particular context, I later discover.

Maybe avoid using it,

I will follow suit for all the BANanoServer based projects going forward. As all the BANano projects are not having any qualms with that, I'll let them be,

Ta!
 
Last edited:
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
I will follow suit for all the BANanoServer based projects going forward. As all the BANano projects are not having any qualms with that, I'll let them be,
Not the good response. All the code should be 100% exchangeable (after all, they both run through EXACTLY the same BANano Engine). Once again : BANanoServer is JUST a jServer, just like a PHP backend etc. Whatever BANano generates is 100% independent from jServer, PHP, etc. It doensn't even know it exists! If something does not work, then it is either:
  1. BANano has an error in Transpiling (but unlikely to me in this case as it works without a jServer, being transpiled by the SAME engine)
  2. Something IS different in your code
For the transpiling of Null in javascript, the Java vs Javascript statement is irrelevant. If you use BANanoServer or not, the generated JavaScript code should be the same:

B4X:
if (_myvar != null) {

}

You either provide me with an example where this works in a stand-alone WebApp and not in one using BANonoServer, or I consider this not a BANano fault, but a logical mistake somewhere from you. If I'm wrong and BANano does generate this statement differently, I gladly admit it and will fix it.

Alwaysbusy
 
Last edited:
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
This sounds harsh. LOL.

A pure example of this class (take any class) that I'm porting over to BANanoServer SHARED, is this, https://www.b4x.com/android/forum/threads/bananoconnect-bananosql-sqlite-mysql-mssql-library.117956/

Just to clarify, the error was happening on these lines on my code inside the SHARED module after I port it without the PHP code of course.

B4X:
types = Null
args = Null

Calling Initialize from SERVER and returning the payload works without any hustles, the issue happened when .Initialize was called by the BROWSER module and

_types.length = 0; was returning the error.

Perhaps its my logic I dont know, Im still new to BANanoServer and SHARED and BROWSER and SERVER modules, however, removing the types = null and args = null has helped solve the issue.

I have attached the working solution class.
 

Attachments

  • BANanoODBC.bas
    34 KB · Views: 245
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
Well, if you make types null and then ask the length of it, I can see the logic why this failes (but it would too in a 'normal', not BANanoServer BANanoApp). And has nothing to do with the your args<>null being changed to args.IsInitialized solution. (Which will not do what you want because it transpiles to if (true) { as JavaScript does not know this concept and is always 'initialized').

Alwaysbusy
 
Last edited:
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
I will make time and draw up and example and attach it here so as to help clarify the problem I experienced.

We can then draw final conclusions after. Thanks for your time.
 
Upvote 0

Harris

Expert
Licensed User
Longtime User
LOL, yep.... but before I went to bed...

Sorry dude...
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…