B4J Question WebSocket server/client question

techknight

Well-Known Member
Licensed User
Longtime User
I am playing around with a Websocket server on B4J, and a client on B4A using the tutorials that Erel has posted in the past.

I noticed when running functions from Server -> client using RunFunction, the data/arguments are a List. But going the other way using SendEventToServer, its a Map.

Is there a way where I can just send JSON both ways instead? Seems kind of Odd to send Lists one way, and Maps the other.

Unless I am not understanding something, but thats how I currently see it. I have everything working without problems, it would be easier for me to just JSON back and forth.

Thanks.
 

LucaMs

Expert
Licensed User
Longtime User
Client-Server data exchange already takes place via JSON, in both directions.

But going the other way using SendEventToServer, its a Map.
You can see that the map is "converted" to a JSON string.


Currently the server performs the reverse conversion, from JSON to Map, but behind the scenes, not in the source code.

This is what I think I understand.

So, to get an exchange of "pure JSON" a big change would be necessary (and an Erel's response is needed :)).
Probably, due to backward compatibility, it would be necessary to add a specific function (again behind the scenes).
 
Upvote 0

techknight

Well-Known Member
Licensed User
Longtime User
The reason why I am bringing this up is cross-compatibility between languages, as I may bring another programmer in here that isnt familiar with B4A/J, etc and may build an app or webpage in the native languages.

so for example if my Websocket server is running in B4J, but, he writes an app using Native PHP/Javascript for the web, or android studio/eclipse/xcode for mobile device to connect to my websocket, How would that be handled?
 
Last edited:
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
so for example if my Websocket server is running in B4J, but, he writes an app using Native PHP/Javascript to connect to my websocket, How would that be handled?
This seems to me a different question, because JSON has nothing to do (directly) with PHP-Javascript.

If your collaborator will only provide you with data in JSON format and you want to receive them in the same format, as I said it will be necessary to modify B4J so that it can receive the JSON string in a websocket class routine; only Erel can do this.
 
Upvote 0

techknight

Well-Known Member
Licensed User
Longtime User
well I mentioned JSON becuase its industry standard?

But it doesnt have to be. All I need to know is how do I communicate with a B4J websocket server with something completely outside of the B4X ecosystem. Thats it. So other programmers/developers can talk back and use the websockets created by B4J.

The way I am doing it now inside the B4X ecosystem is basically how the example was laid out. ws.runfunction on the b4J side, and sendeventtoserver on the b4A side. It just seems proprietary to me.

So if a Javascript programmer was to listen in on the b4J websocket, how would ws.runfunction respond in that environment.

Sorry I have a difficult time explaining whats on my mind and thought processes.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
well I mentioned JSON becuase its industry standard?

But it doesnt have to be. All I need to know is how do I communicate with a B4J websocket server with something completely outside of the B4X ecosystem. Thats it. So other programmers/developers can talk back and use the websockets created by B4J.
And I think it (JSON) can be the right choice but currently the websocket class receives a JSON... converted to a Map.
So WE need an Erel's answer.
 
Upvote 0

techknight

Well-Known Member
Licensed User
Longtime User
Well I just happened to add the WebSocketHandler class to my B4A IDE, and I see how Erel did it for SendEventToServer.

B4X:
'Raises an event on the server. The Event parameter must include an underscore
Public Sub SendEventToServer(Event As String, Data As Map)
    Dim m As Map
    m.Initialize
    m.Put("type", "event")
    m.Put("event", Event)
    m.Put("params", Data)
    Dim jg As JSONGenerator
    jg.Initialize(m)
    ws.SendText(jg.ToString)
End Sub

Sorry I didn't see that before, but thats basically JSON. But instead of sending events, I just want to send data. Problem is, I dont know what other types there are besides "event" so yeap I need Erel.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Looking at the source (here https://github.com/AnywhereSoftware...software/b4j/object/WebSocketModule.java#L137), it looks like the "data" is received, but then it is just assigned to a variable without the possibility to access that variable. Either I'm reading the code wrong (very likely) or there is some unfinished business.

Here's the code (https://github.com/AnywhereSoftware...software/b4j/object/WebSocketModule.java#L110) that converts the incoming JSON to a map (for anything sent back to the server).
 
Upvote 0

techknight

Well-Known Member
Licensed User
Longtime User
Looking at the source (here https://github.com/AnywhereSoftware...software/b4j/object/WebSocketModule.java#L137), it looks like the "data" is received, but then it is just assigned to a variable without the possibility to access that variable. Either I'm reading the code wrong (very likely) or there is some unfinished business.

Here's the code (https://github.com/AnywhereSoftware...software/b4j/object/WebSocketModule.java#L110) that converts the incoming JSON to a map (for anything sent back to the server).

Yea I tried running as data, but it craps out with a java.util.NoSuchElementException, Caused by at java.util.LinkedList.removeFirst(LinkedList.java:270), at anywheresoftware.b4j.object.WebSocketModule$Adapter.onWebSocketText(WebSocketModule.java:138)

This is triggered by the RemoveFirst(); function in the source code link you sent, so chances are that code is this way for a reason as it may be used somewhere else a different way? Not sure.

Otherwise I could remove that line and modify the code to add a BA.RaiseEvent to handle the variable, but again if I edit the existing code, what am I liable to break? thats just it. The code is there for a reason, written that way for a reason otherwise it wouldnt be there.

Edit: Its nice to know the source code for the library is available, because all I have to do is point my companion/hired programmer to that Library for studying and then they can just adapt to its version of websocket handling. Ultimately it would be nice if they learned the B4X ecosystem so then we can just all rejoice and sing kumbya. But ya know. Everyone has their native tongue, and by that I mean native programming language.
 
Last edited:
Upvote 0

OliverA

Expert
Licensed User
Longtime User
java.util.NoSuchElementException, Caused by at java.util.LinkedList.removeFirst(LinkedList.java:270), at anywheresoftware.b4j.object.WebSocketModule$Adapter.onWebSocketText(WebSocketModule.java:138)
Implying, unfinished business.

RunFunction, the data/arguments are a List
Because the JavaScript used to call the function uses apply() and apply expects an array of parameters (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply). Nothing keeps you from sending a JSON string as one of the parameters.
B4X:
Dim someJSON as String = $"{apple: "red"}"$
ws.RunFunction("processSomeJSON", Array As Object(someJSON))
Where ws is the WebSocket variable that was assigned the WebSocket1 argument of the WebSocket_Connected method and processSomeJSON is a JavaScript function in your web page.

Now, the other way around (client to B4J server), you would have to modify the source. Maybe add a "JSON" type that would skip the JSON to map conversion.
 
Upvote 0
Top