B4J Tutorial HTML Web Server

Chapter 1: Introduction​

The minimum code that we need to create a server is as following:
B4X: Copy
Sub Process_Globals
    Public srvr As Server
End Sub

Sub AppStart (Args() As String)
    srvr.Initialize("")
    srvr.Start
    StartMessageLoop
End Sub

The default server port is 8080 if we don't specify it explicitly.
To change the port, use the following code:
B4X: Copy
srvr.Port = 80

Use HttpsFilter to redirect the server to SSL port.
We need to add the following code"
B4X: Copy
srvr.AddFilter("/*", "HttpsFilter", False)

Chapter 2: Serving Static Files​

By default, jServer will read any files inside www folder even you didn't specify the directory.
The server will treat this directory as the assets directory for your static or dynamic website.

Inside www folder, you can put your:
  • HTML files (e.g index.html)
  • Stylesheets, JavaScripts, Images files (e.g styles.css, app.js and icon.png)
Putting html file inside www directory allows client side access it using the full file extension.
For example, if you put an about.html inside www directory, you can access it using http://<domain root>/about.html
Accessing index.html is same as accessing the root path http://<domain root>/
Unless you set the server handler to manage this default behavior.
You can organize your files with sub folders inside www directory and the files with be served following the files system structure.

Example:
Physical files path: /home/myusername/myserverapp/www/images/icon.png (Linux) or C:\MyB4JProjects\MyServerApp\www\images\icon.png (Windows)
Public server path: http://<domain root>/images/icon.png

Chapter 3: Distribute to Production​

Once we have compiled our project in released mode, upload the www directory together with the server.jar from Objects folder to the remote server.

1770886456501.png

To run the server on a Linux VPS, we can use nohup command e.g:
Bash: Copy
nohup /usr/bin/java -jar server.jar > debug.txt &

Chapter 4: Serving Dynamic Contents​

If we want to build a server that serve dynamic contents, we can use ServletResponse.Write to output the contents.
The contents type can be html, json, xml, or other media files.

We can use a server handler to serve a page to the client at the public path: e.g: http://<domain root>/products
We need to add the following code in AppStart:
B4X: Copy
srvr.AddHandler("/products", "ProductsHandler", False)

Put our html files inside our project's "Files" folder during development.
These html files will be treated as our templates.
Read the contents using Files.ReadString.
B4X: Copy
Dim Contents As String = File.ReadString(File.DirAssets, "products.html")
Remember that files put inside "Files" folder will be compiled into the jar file.

Let say we have the following line in our products.html file.
Code: Copy
<h3 class="success">I bought some $PRODUCT$!</h3>
The placeholder string can be replaced or serve from database queries.
Code: Copy
Sub Class_Globals
    Private Response As ServletResponse
End Sub

Public Sub Initialize
 
End Sub

Sub Handle (req As ServletRequest, resp As ServletResponse)
    Response = resp
    Response.ContentType = "text/html"
 
    RenderProductsPage
End Sub

Sub RenderProductsPage
    Dim Contents As String = File.ReadString(File.DirAssets, "products.html")
    Contents = Contents.Replace("$PRODUCT$", "oranges")
 
    Response.Write(Contents)
End Sub

I attached a minimum test server project here to demonstrate some different implementation of a "static" and "dynamic" contents.

References:
https://www.b4x.com/android/forum/threads/server-building-web-servers-with-b4j.37172/
https://www.b4x.com/android/forum/threads/server-run-a-server-on-a-vps.60378/

If you are already familiar building web servers using B4J, consider to use the libraries and framework developed by me.
I hope they can simplify your development work.
 

Attachments

Last edited:
Code: Copy
Sub Handle (req As ServletRequest, resp As ServletResponse)

Thank you so much for this. One of the things that I was failing to understand was this. So ServletRequest is input, i.e. what comes into the server? Just like when one types a URL on the browser that will be input that will be received by the "handler"

And the ServletResponse is what the server sends out, i.e. output, which can be written to the "page" and you see on your webapp?
 
Reupload server.zip in post #1

1. Fixed a typo in products.html
2. Added #CustomBuildAction to create dist.zip
3. Minor adjustments

Edit: Reuploaded again.
Added Conditional Compilation.
B4X: Copy
#If Release
#CustomBuildAction: 2, %JAVABIN%\jar.exe, -cMf dist.zip www %PROJECT_NAME%.jar
#End If
 
Last edited:
Code: Copy
Sub Handle (req As ServletRequest, resp As ServletResponse)

Thank you so much for this. One of the things that I was failing to understand was this. So ServletRequest is input, i.e. what comes into the server? Just like when one types a URL on the browser that will be input that will be received by the "handler"

And the ServletResponse is what the server sends out, i.e. output, which can be written to the "page" and you see on your webapp?
Yes.

Client makes Request to the Server, thus the ServletRequest in the server handler is passing the incoming data to the Handle sub.
The data can be query parameters, headers, content type, request url or body text if the request is HTTP POST or PUT.
B4X: Copy
Request.RequestURI
B4X: Copy
Request.InputStream

When the Server finished processing the Request and wants to return the output to the Client, the Response can be send to the Client from the Server using ServletResponse.Write().
B4X: Copy
Response.Write("<h1>Welcome!</h1>")
The String can be an HTML text provided you have set:
B4X: Copy
Response.ContentType = "text/html"
You can also send JSON or XML with the correct MIME type.
Otherwise, we can use ServletRequest.SendError() or ServletRequest.SendRedirect().
B4X: Copy
Response.SendError(404, "<h1>Page Not Found</h1>")
B4X: Copy
Response.SendRedirect("index.html")
 
Last edited:
Back
Top