B4J Tutorial [WebApp] Chatroom - Threads, Sessions and Server events

Discussion in 'B4J Tutorials' started by Erel, Apr 16, 2014.

  1. Erel

    Erel Administrator Staff Member Licensed User


    Online example: http://basic4ppc.com:51042/chat/index.html

    This example demonstrates several important concepts of the web app framework.

    Multiple pages

    The chatroom is made of two pages. The login page and the chat page.
    The WebSocket is broken when the browser navigates to a different page (or refreshes the current page). The http session allows us to pass data from one page to another. In this example the user name is stored in the login page and then retrieved in the chat page:
    ws.Session.SetAttribute("name", name)

    'chat page
    If ws.Session.HasAttribute("name") = False Then
    'name not found. Go to the login page. This will happen if the user goes to the chat page directly.
       WebUtils.RedirectTo(ws, "index.html")
       name = ws.Session.GetAttribute(
    "name"'remove the attribute
       'the user will be redirected to the login page next time.

    "NewConnection", Me, name)
    End If

    Each WebSocket class instance runs in a different thread (in release mode). This allows many users to be connected at the same time.
    CallSubDelayed was modified in B4J v2.00 to be executed on the target object thread. This allows us to safely call subs in other modules or instances.
    In this example we have a code module named ChatShared. This module holds references to all the active connections and whenever there is a new message it uses CallSubDelayed to notify each of the instances about the new message:
    'ChatShared code module
    'notify each of the connected users about the new message
    For Each c As Chat In connections.Values
    "NewMessage", msg)

    'Chat WebSocket class
    Sub NewMessage(Msg As String)
    "append"Array As Object(Msg))
    End Sub
    The code in code modules will run in the main thread if we call it with CallSubDelayed.
    In this example we call WebUtils methods directly as these methods do not rely on any shared data.

    Server events

    One of the great features of WebSockets is the simple support for server events. Unlike ajax based solutions, the clients don't need to poll the server with endless requests. At any given time the server can send messages to the client.
    There is one extra step with server events. You must call ws.Flush at the end of the event. Flush is called internally in the case of client events.

    Attached Files:

    Last edited: Oct 19, 2017
  2. billzhan

    billzhan Active Member Licensed User

    Erel and miquel like this.
  3. billzhan

    billzhan Active Member Licensed User


    I read the classes tutorial,when comes to the differences between class and code module(B4A):
    I am not sure about some issues,as something, as something changed in B4J:

    1.ChatShared.Init is called in main module, what's the lifecycle of ChatShared (and it's variables, Public AvoidDuplicates and Private connections)?

    2.I think in B4A Public and Private variables can't hold values,is that right?

    3.Can I create more than one thread safe maps in the same way? When I need to re-initital it, Do I just need to call CreateThreadSafeMap again?
    AvoidDuplicates = Main.srvr.CreateThreadSafeMap
    4.Why you use CallSubDelayed instead of call it directly for chat class? Are they the same ?
    CallSubDelayed3(ChatShared, "NewConnection", Me, name)
  4. Erel

    Erel Administrator Staff Member Licensed User

    B4J code modules are not the same as B4A code modules. I recommend you to start with this tutorial: http://www.basic4ppc.com/android/fo...l-for-basic4android-developers.34659/#content

    1. There is no lifecycle to B4J code modules. They exist as long as the process is running.
    2. Not sure that I understand. Variables can holds values.
    3. You can create as many thread safe maps as you want. You can either call AvoidDuplicates.Clear or create a new one with the code you posted.

    4. This is very important point. See the "threads" section in the first post. It is only relevant to server (or WebApps) projects. Each class instance runs in its own thread. If you call ChatShared.NewConnection then this sub will be executed in the class instance thread.
    If you call CallSubDelayed then the target thread will be used to execute the code. In the case of code modules it is always the main thread.
    Last edited: Aug 17, 2014
  5. Irips

    Irips New Member


    Is possible run without the port 51042?

  6. Erel

    Erel Administrator Staff Member Licensed User

    You can run it with any port you like.
  7. Rick Harris

    Rick Harris Well-Known Member Licensed User

  8. Erel

    Erel Administrator Staff Member Licensed User

  9. slamarca

    slamarca Member Licensed User

    Hi Erel, in line 20 of module Chat.bas should be "ws.Session.RemoveAttribute("name")" in place of "RemoteAttribute".
    Btw, are there any docs on WebSocket and JqueryElement methods and properties?
    UPDATE: I've found them....

    Keep up the good work!

    Sergio from Italy
    Last edited: Jun 28, 2014
  10. LucaMs

    LucaMs Expert Licensed User


    I guess this means that in this specific case (ChatShared.NewConnection) is better that the code is executed in the "routine's thread" (Main for modules), since in the example "[Server] Login System & Filters Tutorial", in the SigninHelper (which runs in its own thread, if I understand well) there is this call (DB is a module):

    success = DB.CheckCredentials (userName, password)

    (I bought an electron microscope and found: "B4J code modules are not the same as B4J code modules". An incorrect character: unforgivable :D)
  11. Erel

    Erel Administrator Staff Member Licensed User

    Replace the second J with A...

    Not sure that I fully understand your question. NewConnection is executed by the mian thread (because of the CallSubDelayed call).

    The current code in this sub shouldn't be run by other threads.
  12. LucaMs

    LucaMs Expert Licensed User

    Reading well my question ... even I understand it.
    56 hours have passed: too much for my memory.
    victormedranop likes this.
  13. LucaMs

    LucaMs Expert Licensed User

    Now i understand my "question".

    The two calls are in handler classes and both call a function in a module.

    For this reason, I wrote: "I guess this means that in this specific case".
  14. LucaMs

    LucaMs Expert Licensed User

    So, if I want to use a generic function of a module I can run it in the thread of a websocket handler by calling it by CallSub. But it is possible, in this way, that two classes use that routine simultaneously without interference?

    Otherwise, I was thinking to use a class for the utility routines and create an instance of this class within the websocket handler.
    Last edited: Aug 20, 2014
  15. Erel

    Erel Administrator Staff Member Licensed User

    You don't need to use CallSub in this case. Just call it directly.
    There is no problem with running the same code concurrently. Only if the code is accessing global variables then it can be problematic. If you are not sure then it is better to use CallSubDelayed and run all the shared stuff on the main thread.
    LucaMs likes this.
  16. LucaMs

    LucaMs Expert Licensed User

    Thanks, Erel
  17. masmukti

    masmukti Member Licensed User

    Hi Erel,
    I got an error like this,
    whats the problem? Chatroom Error.png
  18. Erel

    Erel Administrator Staff Member Licensed User

    This is a community forum, please don't start all your questions with Hi Erel.

    The link is not correct. There is no chat folder.
  19. masmukti

    masmukti Member Licensed User

    what do you mean the link is not correct?
    i am running in local host, and compiling is success
  20. Erel

    Erel Administrator Staff Member Licensed User

    The link should be ...51042/index.html
  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