B4J Tutorial [Server] Building web servers with B4J

Discussion in 'B4J Tutorials' started by Erel, Jan 27, 2014.

  1. Erel

    Erel Administrator Staff Member Licensed User

    Edit: Web Apps tutorial: http://www.basic4ppc.com/android/forum/threads/webapp-web-apps-overview.39811/

    The server implementation is based on a popular and powerful Java server library named Jetty (license)
    The database connection pooling implementation is based on c3p0 (license).


    B4J Server features:
    • High performance web server
    • Automatic handling of static files
    • Simple to develop custom "handlers"
    • Support for GET and POST requests
    • Support for multipart requests (file uploads)
    • Standard logging
    • Each handler can either be multi-threaded or single-threaded
    • Simple and powerful database connections pooling
    • Server can run on Windows, Mac and Linux (including board computers such as Raspberry Pi)

    Possible usages
    • Internal or external web sites
    • Backend solutions (with or without UI) that can optionally connect to any type of database


    If you never worked with web servers then it is recommended to start with a HTTP tutorial such as this one: http://net.tutsplus.com/tutorials/t...rotocol-every-web-developer-must-know-part-1/

    I also recommend you to use a proper browser with debugging plugin such as FireFox + FireBug. The ability to inspect the requests and responses is very useful.

    How it works

    A server program is a non-UI program.
    In the Main module you should create a Server object, configure it, start it and call StartMessageLoop:
    Code:
    Sub Process_Globals
       
    Private srvr As Server
    End Sub

    Sub AppStart (Args() As String)
       srvr.Initialize(
    "srvr")
       srvr.Port = 
    8888
       srvr.StaticFilesFolder = 
    File.Combine(File.DirApp, "www")
       srvr.AddHandler(
    "/hello""HelloPage"False)
       srvr.AddHandler(
    "/FormExampleHelper""FormExampleHelper"False)
       srvr.AddHandler(
    "/FileUpload""FileUpload"False)
       srvr.Start
       StartMessageLoop
    End Sub
    As you can see in the above code, the port is set to 8888.
    StaticFilesFolder sets the folder (and subfolders) that will be used to serve static files. Any file that is not generated by your code is a static file (html, js, css, images, etc.).
    Files outside of this folder cannot be accessed. This is important for security reasons.
    Note that if the url points to a folder then the index.html file in that folder will be served (if it exists).

    Handlers

    A handler is a B4J class that is mapped to a URL. A handler class is responsible for getting the request and providing the response.

    Each request is handled by a new instance of the handler class. A handler class should have an empty Initialize and a Handle sub with the following signature:
    Code:
    Sub Handle(req As ServletRequest, resp As ServletResponse)
    You should read the data from the ServletRequest and write the response to the ServletResponse.

    For example:
    Code:
    Sub Handle(req As ServletRequest, resp As ServletResponse)
    resp.Write(
    "Hello World!")
    End Sub
    The attached example includes three handlers:
    HelloPage - A simple handler that creates the following page:

    [​IMG]
    Note that this page was served from a Raspberry Pi board :)

    FormExampleHelper - This handler receives a submitted form and prints the form's fields. It is used by two html pages. A simple form page and a page that uses Ajax (with JQuery) to send the form.

    FileUpload - This handler receives a multipart form with a file and other fields. It logs the fields and the file size.

    Threading

    When you add a handler you need to specify whether you want it to be a single threaded handler or a multithreaded handler. By default you should use multithreaded handlers (third parameter should be false).

    A multithreaded handler means that your handler code will be run by a thread from the server threads pool. Multiple instances of the same handler and other handlers can be executed in the same time. As long as you don't access any global variable out of the current handler instance you should be safe.

    A single threaded handler will always be executed by the main thread. This means that if there are multiple requests they will be queued and executed one by one. Single threaded handlers can be useful in many cases. Some examples:
    - A handler that accesses a SQLite database, which is less suitable for concurrent connections. See this tutorial for concurrent access to SQLite: https://www.b4x.com/android/forum/t...ent-access-to-sqlite-databases.39904/#content
    - A handler that writes to a specific file.
    - A handler that sends a job to the printer

    Note that when you run your code in Debug mode the handlers will always run in the main thread.

    Datebase Connections Pooling

    Many web servers are based on databases. Databases, such as MySQL and others, can properly handle concurrent queries and transactions. The ConnectionPool object handles a pool of database connections. You can then get a connection (SQL object) from the pool, work with it and close it, which will actually return it to the pool.

    The pool is responsible for maintaining the connections.
    An alternative for a connections pool is a process global SQL variable. However for it to work properly all the handlers should be single threaded handlers.

    As explained in the SQL tutorial you should use #AdditionalJar attribute to add a reference to the JDBC jar. You should then make a public process global pool variable and use it from the handler.


    To try this example, run it from B4J and point the browser to 127.0.0.1:8888
    This will load the index.html file that is available in the www folder.

    Examples & Tutorials:

    Online examples: https://www.b4x.com:51041
    Other server tutorials: http://www.basic4ppc.com/android/forum/pages/results/?query=[server]&page=1&prefix=0
     

    Attached Files:

    Last edited: Aug 9, 2017
  2. merlin2049er

    merlin2049er Well-Known Member Licensed User

  3. warwound

    warwound Expert Licensed User

    Very interesting....
     
  4. BPak

    BPak Active Member Licensed User

    Ran the example on my XP machine.

    Works with the web pages except the FileUpload which shows an error in the /www folder (MultiPart6824877830187166037)

    Code:
    Parsing code.                           0.02
    Compiling code.                         
    0.09
    Compiling generated Java code.          Error
    Cannot find: C:\Program Files (x86)\Anywhere Software\B4J\libraries\jxl.jar
     
  5. warwound

    warwound Expert Licensed User

    The example works fine here.
    That's on a 64 bit Windows 7 vmware virtual machine.

    Martin.
     
  6. Erel

    Erel Administrator Staff Member Licensed User

    @BPak this is not an error. The Multipart6... is the temporary file that was uploaded. You can see in the handler code that the target folder is the www folder.

    How is this compilation error related?
     
  7. BPak

    BPak Active Member Licensed User

    C:\Program Files (x86)\Anywhere Software\B4J\libraries\jxl.jar

    The installation done on the 32bit XP system was made to following folders:
    C:\Anywhere\B4J
    C:\Anywhere\basic4android

    The error shows the prog is looking under program files (x86) which does not exist on that computer.
     
  8. Erel

    Erel Administrator Staff Member Licensed User

    Do you get this error when you compile the server project?
     
  9. BPak

    BPak Active Member Licensed User

    No - It compiles correct and says in the Logs
    Program started
    four red lines of info
    Server started.

    I start Chrome browser and enter the ip address
    The index page is displayed.
    click upload file
    select a file to upload and click the submit button.

    Looking in folder /www at the Temp file.
    The message I posted is found within it.

    Program still runs and works as if there is no error.

    Originally the jxl.jar file was not in the installation Libraries. So I copied it from my main computer and put it in the library. This did not change the message in the Temp file.

    EDIT:

    Resolved. My error. Now works without any error. Sorry for any inconvenience!
     
    Last edited: Jan 29, 2014
  10. souzafo

    souzafo Member Licensed User

    How to start/stop server?
    The server can run as a Windows service, for example, running on Windows 2003 or 2008?
     
  11. giga

    giga Well-Known Member Licensed User

    Awesome work Erel,

    Couple things I have discovered:

    My IE11 did not work with either loopback 127.0.0.1:8888 or IP
    (ISP's DNS search page came up instead) http://www.dnsrsearch.com/search.php?search=192.168.1.1:8888/hello&src=10

    FireFox came right up with 127.0.0.1:8888 or IP 192.168.1.1:8888

    it shows in the taskmanager as javaw.exe. Can this name be changeable in order to be found easier also in order to tell if it is running?

    KUDOS to you for the great work.:)
     
  12. Erel

    Erel Administrator Staff Member Licensed User

    About the IE11 issue: http://stackoverflow.com/questions/17415111/127-0-0-1-will-not-work-in-ie-11

    You can create a batch file that runs the server. Basically you just need to call Java -jar <your jar file>. You will then see the logs in the cmd window.
    This is how RDC (which is a similar server written in Java) should be installed: http://www.basic4ppc.com/android/fo...ase-connector-connect-to-any-remote-db.31540/

    You can schedule it to start when the computer is booted. You can also redirect the standard error and standard output to a file.

    You can use a tool such as this tool to create a service if you like: http://nssm.cc/

    To convert it to a standard Windows EXE program (with its own process name):
    Create Windows native executables (exe files)
     
    Last edited: Jan 30, 2014
    Gabino A. de la Gala likes this.
  13. gudino jose luis

    gudino jose luis Active Member Licensed User

  14. JOTHA

    JOTHA Well-Known Member Licensed User

    I'm sorry. I tried to run it, but this message came:
    Do I need a library?
     
  15. Erel

    Erel Administrator Staff Member Licensed User

    Seems like you are not using v1.50. Check the about box.
     
  16. JOTHA

    JOTHA Well-Known Member Licensed User

    Yes, you are right. I'm using 1.0!
    Thank you for the answer.

    I'll install the actual version ant try again ... ;-)
     
  17. vcelak

    vcelak Member Licensed User

    Is possible to change server's signature (powered by jetty://)? Also will be great to have way to set handlers for specific error codes like 404 etc. - to serve default web page or do some other job e.g. redirection
     
  18. Erel

    Erel Administrator Staff Member Licensed User

    The "powered by jetty" only appears when there is an error. Please post a feature request in the wishlist forum for custom error pages.
     
  19. SAM ShamsulBahrim

    SAM ShamsulBahrim Member Licensed User

    I wish to see many more "specific examples" of the web server. Simple CRUD web apps on MySQL, cookies web app, etc.

    Thank you.

    SAM
     
  20. wl

    wl Well-Known Member Licensed User

    Hi,

    Great work! Is there any chance of having the statisticfilesfolder depend on the requested hostname?
     
Loading...
  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