Correct. This is a full blown stand-alone Jetty server (must run on a VPS)
Exactly. You may look a bit to this like this serves as e.g. node.js where you can even access the hardware, a database, do some MQTT or Bluetooth stuff, etc. In short, everything a normal B4J app can do. One could for example have a Raspberry Pi that regulates the temperature in your home, running the server part. And from any browser in the world, you can connect to this Jetty server and change the temperature.
Correct. You get the best of both worlds using only one programming language: B4J!
This is just convenient as a lot of ‘logic’ may be the same on both the server (B4J Java) and the Browser side (Javascript). For example a class that holds the structure of a database record:
' a very generic record definition that can be used for about anything
Sub Class_Globals
Public UUID As String ' must be a UUID/GUID to allow for syncing
Public LinkUUID As String ' must be a UUID/GUID to allow for syncing
Public RecordType As Int ' to identify the type of record
Public Created As String '
Public LastModified As String '
Public Status As Int
Public Strings(SHAREDSyncDB.MAX_STR) As String
Public Numbers(SHAREDSyncDB.MAX_NUM) As Double
Public const STATUS_UNDEFINED As Int = 0
Public const STATUS_NEW As Int = 1
Public const STATUS_UPDATED As Int = 2
Public const STATUS_DELETED As Int = 3
Private EmptySTR As List
Private EmptyNUM As List
End Sub
'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
EmptySTR.Initialize
For i = 0 To SHAREDSyncDB.MAX_STR - 1
EmptySTR.Add("")
Next
EmptyNUM.Initialize
For i = 0 To SHAREDSyncDB.MAX_NUM - 1
EmptyNUM.Add("")
Next
End Sub
Public Sub ToMapJSON() As Map
' keys are lowercased!
Dim m As Map
m.Initialize
m.Put("uuid", UUID)
m.Put("linkuuid", UUID)
m.Put("recordtype", RecordType)
m.Put("created", Created)
m.Put("lastmodified", LastModified)
m.Put("status", Status)
m.Put("strings", Strings)
m.Put("numbers", Numbers)
Return m
End Sub
public Sub FromMapJSON(m As Map)
' keys are lowercased!
UUID = m.GetDefault("uuid", "")
LinkUUID = m.GetDefault("linkuuid", "")
RecordType = m.GetDefault("recordtype", 0)
Created = m.GetDefault("created", "2000-01-01T00:00:00")
LastModified = m.GetDefault("lastmodified", "2000-01-01T00:00:00")
Status = m.GetDefault("status", STATUS_UNDEFINED)
Strings = m.GetDefault("strings", EmptySTR)
Numbers = m.GetDefault("numbers", EmptyNUM)
End Sub
public Sub FromMapRECORD(m As Map)
UUID = m.GetDefault("uuid", "")
LinkUUID = m.GetDefault("linkuuid", "")
RecordType = m.GetDefault("recordyype", 0)
Created = m.GetDefault("created", "2000-01-01T00:00:00")
LastModified = m.GetDefault("lastmodified", "2000-01-01T00:00:00")
Status = m.GetDefault("status", STATUS_UNDEFINED)
For i = 0 To SHAREDSyncDB.MAX_STR - 1
Strings(i) = m.GetDefault("s" & i, "")
Next
For i = 0 To SHAREDSyncDB.MAX_NUM - 1
Numbers(i) = m.GetDefault("d" & i, 0.0)
Next
End Sub
public Sub ToListRECORD(ForInsert As Boolean) As List
Dim l As List
l.Initialize
If ForInsert Then
l.Add(UUID)
End If
l.Add(LinkUUID)
l.Add(RecordType)
If ForInsert Then
Created = SHAREDSyncDB.LongToDateTime(DateTime.Now)
l.Add(Created)
End If
l.Add(LastModified)
l.Add(Status)
For i = 0 To SHAREDSyncDB.MAX_STR - 1
l.Add(Strings(i))
Next
For i = 0 To SHAREDSyncDB.MAX_NUM - 1
l.Add(Numbers(i))
Next
If ForInsert = False Then
l.Add(UUID)
End If
Return l
End Sub
Instead of having to write such a class for the server, and an identical one for the browser, they can both share this code. For the Server it will be compiled to Java by B4J, and for the browser it will be Transpiled to Javascript by BANano. The usage of this class is the same for both.
Moreover, in such a class you can use #If B4J:
So say, in a SHAREDClass, there is something specific for the Server, you can do this:
public Sub UPDATEIsSyncedWait()
Dim Query As String
#if B4J
Try
' in case of the server, it is the queue we have to update
Query = $"UPDATE tQueue SET queuestatus=${SYNC_DONE} WHERE queuestatus=${SYNC_LOCKED}"$
SQL.ExecNonQuery2(Query, Null)
Catch
Log(LastException)
End Try
#else
' in case of the browser, we update the status of the sync in tRecords
Query = $"UPDATE tRecords SET syncstatus=${SYNC_DONE} WHERE syncstatus=${SYNC_TODO}"$
SQL.ExecuteWait(Query, Null)
#End If
End Sub
Probably a typo and you mean BROWSERPage/SERVERPage, but this is how it is:
(I’ve named them here Page and Class to distingush, but of course in reality both are just B4J classes)
- Every BROWSERPage (this is a page with WebSockets) must have a 1:1 to a SERVERPage (who also has a WebSocket)
- Every other BROWSERClass (not a WebSocket entry point, but e.g. a helper class) does not need a SERVERClass
- Same, You can have helper SERVERClasses and modules that do not have a BROWSERClass equivalent. (for example just a REST API hander).
The key here is the Websocket. If it has a Websocket entry point in the browser class then it means it wants to talk with its server equivalent, who also has a Websocket entry point.
These two page can talk with each other, as a WebSocket is bi-directional. So the SERVERPage can call a method in a BROWSERPage, and the other way around.
For example a BROWSERPage can insert some info from a DB record just by calling the method on the SERVERPage:
In SERVERPage the definition:
Sub INSERTSomethingInDB(Something...) as Boolean
' normal B4J stuff to run an insert query in a database
Return successOrNot
End Sub
In BROWSERPage the call:
Dim value As Int = 0
Dim prom As BANanoPromise = ws.RunFunctionWithResult("INSERTSomethingInDB", Array(Something...))
prom.Then(value)
Log("SERVER insert a success " & value)
prom.end
Equally, the SERVERPage can make a call e.g. to find out the user language the Browser is to the BROWSERPage:
In BROWSERPage the definition:
Sub GetBrowserLanguage() as String
Return BANano.Navigator.GetField("language").Result
End Sub
In SERVERPage the call:
Dim fut As Future = ws.RunFunctionWithResult("GetBrowserLanguage", Null)
ws.Flush
Log("BROWSER says language is =" & fut.Value)
In summary:
The SERVER prefix lets the Transpiler know it has to be compiled for Java, not Javascript
The BROWSER prefix lets the Transpiler know it has to be transpiled to Javascript (so can only contain BANano compatible code)
The SHARED prefix lets the Transpiler know it has to be compiled to Java AND to JavaScript (contains BANano compatible code and #If B4J if some parts are for the SERVER only).
Alwaysbusy