B4J Question [BANanoServer] [SOLVED] How can I listen for HTTP Payload data?

alwaysbusy

Expert
Licensed User
Longtime User
You better remove the BANanoServer prefix to get more replies as this sounds like a standard B4J jServer handler question. jServer Handlers process incoming HTTP requests. Some more info on how your HTTP Request payload looks like would help. Just make sure your handler class name starts with SERVER.
 
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
This is what is being sent by them whenever some event happens

B4X:
POST http://xxx.xx.xx.xxx:xxxx HTTP/1.1
content-length: 85
accept-language: fr
host: xxx.xx.xx.xxx:xxxxx
content-type: application/json
accept-encoding: gzip,deflate
accept-charset: UTF-8;q=0.9,*;q=0.7
user-agent: SIGFOX

{
  "device":"(redacted)",
  "seqNumber":"(redacted)",
  "data":"(redacted)"
}

And I am only interested the JSON part of the above string.

I think this what I wanted to have green lights about when doing this with the BANanoServer

Just make sure your handler class name starts with SERVER.
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
Just make sure your handler class name starts with SERVER.
I think this what I wanted to have green lights about when doing this with the BANanoServer
In fact, it will work without the SERVER prefix, but I strongly advice to use it as when your project grows bigger, it will help you a lot in identifying which part does what exactly. And it helps a lot for debugging and posting questions if you use it too.

BROWSER and SHARED are not optional.

And that payload looks like a normal B4J jServer handler request so no problem to process it.

Alwaysbusy
 
Last edited:
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
I really appreciate your advise. Actually, this is the CRUX of our projects life cycle, if it does'nt work, eish.

My current implementation is 2 BANano WebApps, a client app and a admin app, as these do two different things, splitting it like that makes much more sense, for maintenance and other things.

Thing is, we have an extra "b4j server" app receiving the payload and writing this to the database via RDC. My "admin app" then uses this database information, same as the "client app".

The reason I started learning about the BANanoServer is because I believe its capable to do all this, instead of me having 3 apps running here, I have 2, the BANanoServer WebApp and then BANano WebApp.

This means, my "admin app" gets converted from being a normal BANano WebApp to be a BANanoServer WebApp, handling the payload and database CRUD. So my decision rests on BANanoServer being able to handle the payload and saving it to the database. Before I can think of adding a single page on the BANanoServer implementation, I need to ensure that BANanoServer can listen and get the payload data, its only then and only then will I be able to continue implementing the plans further. ;)

TheMash
 
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
Wow, so far I'm able to use some of the code. I've selected all the libraries I am using on my b4j project so that my BANanoServer project also uses them.

I am not in anyway polling any REST API but receive the content and just need to process it. This means we need some listener of some sort.

Shucks, you said the BANanoServer = "jServer" and my "b4j app" is using the "jNetwork" library, and the jNetwork exposes other functions like .listen and also the Socket class.

This is the mind boggling area for me. There is no way to "bridge" this by some magic formulae? LOL.

BANanoServer
B4X:
Private mSrvr As Server

B4X:
Public server As ServerSocket
Private client As Socket

My b4j code is like this

B4X:
        'listen for connections
        server.listen
        'for for a connection to be made
        Wait For server_NewConnection (Successful As Boolean, NewSocket As Socket)
        Log("New Connection...")
        If Successful Then
            If astream.IsInitialized Then
                astream.Close
            End If
            client = NewSocket
            astream.Initialize(client.InputStream, Null, "astream")
        End If
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
I wouldn't be concerned about splitting things up. In our main app in my day job , we run several jServers (I think for the moment 20 all together) that all talk with each other via handlers, MQTT or other communication system. This frees up resources so the Clients WebApp keeps being very fast and responsive.

Every app we write starts either as an ABMServer or a BANanoServer project. Simplified versions released here because you can immediately start with your business logic.

So our App consists of several such apps, all handling specific tasks:
  • Client WebApp in ABM
  • Client WebApp in BANano for entering data on the work floor
  • Admin WebApp for us to set options and enable/disable extra features in the Client WebApp, depending on what they pay for)
  • Several T0001 (which handles tasks from the others, queue based in the background like making inventories and creating reports/mailing them to the ones responsible for it etc)
  • Several P0001 (which handle processing of the data coming from our scanners)
  • API for the Client to access the DB (or other e.g. external Billing and Warehouse tools use this to get/put data in our databases)
  • Monitor (to which all apps report to at a certain interval so the server can restart them if something went wrong)
  • Billing (inhouse WebApp to automatically bill our clients)
  • Launcher WebApp (to launch or stop instances of the other apps e.g. if we do updates there is no downtime)
  • ...

By this design, we can very fast adept if e.g. de API takes up to many resources we can put it (or several instances of it) on another physical server in minutes. Such a design is needed as we handle a lot of traffic.

Alwaysbusy
 
Last edited:
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
jServer and jNetwork are two completely different technologies. I would get rid of the jNetwork and just make a jServer Hander to do the same thing. And the incoming inputstream will only contain your request body (the json part, as the request is split up) so it will be much easier to process. Plus you take advantage of the pooling from jetty.
 
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
I would get rid of the jNetwork and just make a jServer Hander to do the same thing.
If I take this option, by default, jServer is already listening to whatever port its running from. I just need to get the payload. Ok,

If I'm right, this should happen inside this call, as it receives any incoming connections?

B4X:
Private Sub WebSocket_Connected (WebSocket1 As WebSocket)
    Log("Connected")    
    ws = WebSocket1    
    ' Lets update the cache with this class
    CacheReport = Main.Server.UpdateFromCache(Me, ws)
    Log("PageID: " & CacheReport.BANPageID)
    Log("Comes From Cache:" & CacheReport.ComesFromCache)
    Log("Is a reconnecting socket: " & CacheReport.IsReconnected)
    Main.server.SendConnected(ws)
End Sub
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
No. You need a normal jServer handler:

1610481044339.png


And add it to the jServer (or the BANanoServer in this case) in main:
B4X:
Server.AddHandler("/myhandler", "SERVERHandler", False)

You didn't use that in the time you worked with ABM? It is the same.

Alwaysbusy
 
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
Ok, spent some time reading and going through the jServer documentation. You were right, I love it. I managed to relate it to how I have experienced VueJS and it made a lot of sense to me. At most I wont have to change configurations and other things.

Anyway, this is what I ended up writing (to clean it up later)

B4X:
Public Sub Initialize
    Log("SigFox initialized....")
    SHAREDUtility.Initialize
End Sub

Sub RequestData(ins As InputStream) As Map
    Dim data As Map = CreateMap()
    Try
        Dim tr As TextReader
        tr.Initialize(ins)
        Dim json As JSONParser
        json.Initialize(tr.ReadAll)
        data = json.NextObject
    Catch
        LogDebug("[User/RequestData] " & LastException)
    End Try
    Return data
End Sub

Sub Handle(req As ServletRequest, resp As ServletResponse)
    mreq = req
    mresp = resp
    'get the payload
    Dim payload As Map = RequestData(req.InputStream)
    Log("New Payload...")
    Log(payload)
    SHAREDUtility.ReturnJSON(payload, resp)   
End Sub

I tested this manually and it returned {}.

I created the callback function on the server and my payloads are just coming fine.

Perfect. Thanks a lot.

PS: I have asked a lot of questions..
 

Attachments

  • 1610508435782.png
    1610508435782.png
    55.1 KB · Views: 52
Last edited:
Upvote 0
Top