B4J Tutorial [WebApp] Hello World Web App

In this tutorial we will develop the following web app:

SS-2014-04-10_15.45.57.png


There are three components to this solution:

Main module: configures the server and the handlers and web sockets.

In this case we have a single WebSocket. It is mapped to a url which we later need to set in the html file.
The WebSocket class name is HelloWorld.
B4X:
Sub Process_Globals
   Public srvr As Server
End Sub

Sub AppStart (Args() As String)
   srvr.Initialize("srvr")
   srvr.AddWebSocket("/ws", "HelloWorld")
   srvr.Port = 51042
   srvr.Start
   StartMessageLoop
End Sub

WebSocket class: These classes are similar to Basic4android Activities. An instance of this class will be created each time that a connection is made (to the WebSocket url). The connection can stay alive for many hours. It will break when the user navigates to a different page or closes the browser.

Each instance runs in a different thread. This means that many users can be connected at the same time.
Note that in Debug mode a single thread is used to handle all instances.

Client user interface: The user interface is written in Html / CSS. You should add a reference to the small b4j_ws.js JavaScript file. This script manages the communication between the server and the client.
You are free to use any html elements you like. Including third party libraries.
There should also be a reference to jQuery library. jQuery is a very popular JavaScript library that makes it simpler to access and manipulate the document elements.

In our case we have two fields (text1 and text2) a button and a result paragraph (<p>):
B4X:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Web App Hello World!</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
  <link rel="stylesheet" type="text/css" href="index.css" />
  <script src="/b4j_ws.js"></script>
</head>
<body>
  <h1>Web App Hello World!</h1>
  <p id="plog"></p>
  <div id="maindiv">
  First Number: <input id="text1" type="text"></input><br/>
  Second Number: <input id="text2" type="text"></input><br/>
  <button id="btncalc">Calculate</button><br/>
  <p id="result"></p>
  </div>
   <script>
  //connect to the web socket when the page is ready.
  $( document ).ready(function() {
  b4j_connect("/ws");
  });
   </script>
</body>

All the elements that you need to interact with from the server code must have lower case ids.

The WebSocket code:
B4X:
Sub Class_Globals
   Private ws As WebSocket
   Private text1, text2, btnCalc, Result As JQueryElement
End Sub

Public Sub Initialize
End Sub

Private Sub WebSocket_Connected (WebSocket1 As WebSocket)
   Log("Connected")
   ws = WebSocket1
End Sub

Sub btnCalc_Click (Params As Map)
   Dim ft2 As Future = text2.GetVal
   Dim ft1 As Future = text1.GetVal
   If IsNumber(ft1.Value) AND IsNumber(ft2.Value) Then
     Result.SetText("The result is: " & (ft1.Value + ft2.Value))
   Else
     Result.SetText("Invalid numbers")
   End If
End Sub

There are 4 JQueryElement global variables. These variables will be mapped to the html elements automatically. Events such as btnCalc_Click event will also be mapped automatically.
All we need to do is write the code in the event.

JQueryElement provides access to all of the jQuery elements methods.
http://api.jquery.com/

The WebSocket itself (ws in this case) allows you to call any JavaScript function and also to create JavaScript code at runtime and run it (eval / new function).

In this example we want to add the two values. We get the user input with GetVal method and then set the text of the 'result' element.

Network latency

When you test the web app from the IDE then the time it takes for a message to get from the server to the client is very short. This is also true if the server and the client are located in the same local network.
However this is not the case with internet web apps. The server can be very far from the clients. This means that we need to make sure that the communication code is optimized.
B4J web app framework will help you to write optimize code.

WebSocket and JQueryElement methods that return values do not return the actual value directly. Instead they return a Future object and immediately continue to the next statement.
When you call Future.Value the current thread will wait until the value is available (if it is not already available).
The correct design is quite simple. When the event starts you need to get all the future values that later are needed.
Only then you should call Future.Value. This allows you to get all the values in a single round trip (Server -> Client -> Server).

Tip: Server.DebugNetworkLatency property allows you to emulate the network latency. During debug deployments an artificial latency is added to server -> client -> server round trips. The default value is 100 (milliseconds).

Tools
  • You should use a browser development tool such as Firefox FireBug or Chrome development tool during development. Once you learn how to work with these tools your productivity will be much higher.
  • Adobe Brackets is a free tool that helps with writing the html / css code: http://brackets.io/
    You can of course use other similar tools or Notepad++
It is recommended to learn the basics of jQuery: http://learn.jquery.com/
jQuery is quite simple and will make it easier to integrate all kinds of jQuery plugins like done in this example:
http://basic4ppc.com:51042/dbutils/index.html

The project is attached. The static files are located under Objects\www.
 

Attachments

  • WebAppHelloWorld.zip
    3.2 KB · Views: 3,767
Last edited:

lucdrb

Active Member
Licensed User
Longtime User
Hi,

I try to run the program with the bridge (running from /home/pi) on a Raspberry Pi but I couldn't see the web page.

Raspberry Pi side:

^Cpi@raspberrypi~ $ sudo java -jar b4j-bridge.jar
B4J-Bridge v1.00
Waiting for connections (port=6790)...
My IP address is: 192.168.0.12
Connected!

Log when I run the program
2015-06-25 10:19:18.369:INFO::main: Logging initialized @2344ms
2015-06-25 10:19:20.226:INFO:eek:ejs.Server:main: jetty-9.1.z-SNAPSHOT
2015-06-25 10:19:20.698:WARN:eek:ejh.MimeTypes:main: java.util.MissingResourceException: Can't find bundle for base name org/eclipse/jetty/http/encoding, locale en_GB
2015-06-25 10:19:21.372:INFO:eek:ejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@a8195f{/,file:/home/pi/tempjars/www,AVAILABLE}
2015-06-25 10:19:21.420:INFO:eek:ejs.AbstractNCSARequestLog:main: Opened /home/pi/tempjars/logs/b4j-2015_06_25.request.log
2015-06-25 10:19:21.749:INFO:eek:ejs.ServerConnector:main: Started ServerConnector@1790bfe{HTTP/1.1}{0.0.0.0:51042}
2015-06-25 10:19:21.769:INFO:eek:ejs.Server:main: Started @6270ms

Raspberry Pi side
Starting program

Chrome explorer side
HTTP ERROR: 404
Problem accessing /. Reason:

Not Found
Powered by Jetty://

I've try with the jar program in the same directory /home/pi
pi@raspberrypi~ $ sudo java -jar WebAppHelloWorld.jar

2015-06-25 10:04:09.322:INFO::main: Logging initialized @2169ms
2015-06-25 10:04:11.152:INFO:eek:ejs.Server:main: jetty-9.1.z-SNAPSHOT
2015-06-25 10:04:11.622:WARN:eek:ejh.MimeTypes:main: java.util.MissingResourceException: Can't find bundle for base name org/eclipse/jetty/http/encoding, locale en_GB
2015-06-25 10:04:12.283:INFO:eek:ejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@a8195f{/,file:/home/pi/www,AVAILABLE}
2015-06-25 10:04:12.328:INFO:eek:ejs.AbstractNCSARequestLog:main: Opened /home/pi/logs/b4j-2015_06_25.request.log
2015-06-25 10:04:12.653:INFO:eek:ejs.ServerConnector:main: Started ServerConnector@b8eb53{HTTP/1.1}{0.0.0.0:51042}
2015-06-25 10:04:12.661:INFO:eek:ejs.Server:main: Started @6032ms

Same error in the Chrome explore

Help please
Many thanks in advance

Luc
 

lucdrb

Active Member
Licensed User
Longtime User
:DIt's working :D

Should i've to do that for all the program when I use the jetty server?

Thanks for your help.
 

United Technical Support

Member
Licensed User
Longtime User
Erel,

When I compile this WebAppHelloWorld.zip with B4J 3.50, it show the error as:

2015-08-04 18:47:35.436:INFO::main: Logging initialized @182ms
2015-08-04 18:47:35.545:INFO:eek:ejs.Server:main: jetty-9.1.z-SNAPSHOT
2015-08-04 18:47:35.561:WARN:eek:ejh.MimeTypes:main: java.util.MissingResourceException: Can't find bundle for base name org/eclipse/jetty/http/encoding, locale zh_HK
2015-08-04 18:47:35.608:INFO:eek:ejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@1065c63{/,file:/C:/Documents%20and%20Settings/Owner/My%20Documents/B4j-project/WebAppHelloWorld/Objects/www/,AVAILABLE}
2015-08-04 18:47:35.608:INFO:eek:ejs.AbstractNCSARequestLog:main: Opened C:\Documents and Settings\Owner\My Documents\B4j-project\WebAppHelloWorld\Objects\logs\b4j-2015_08_04.request.log
2015-08-04 18:47:35.748:INFO:eek:ejs.ServerConnector:main: Started ServerConnector@1cdf38{HTTP/1.1}{0.0.0.0:51042}
2015-08-04 18:47:35.748:INFO:eek:ejs.Server:main: Started @513ms

But I simple copied the Object\www\* to C:\Documents and Settings\Owner\My Documents\B4j-project\WebAppHelloWorld\Objects\www\, that is OK now.
Yes, http://10.13.0.9:51042/index.html can have the result now.

But all errors still happen again. Can I setup something to make the error disappear. It is very annoying, thanks!
 
Last edited:

Zoltan Dinya

Member
Licensed User
Longtime User
Hello Erel!
The B4J is great, but I am a real beginner in the web programming, and I hope that You can help me.... When I try to run the web app, I get this: "WebSocket connection to 'ws://212.(my IP).114:51042/ws' failed: Error during WebSocket handshake: Unexpected response code: 404"

The index.html is ok, but the function button doesn't work. 404 error. I send also 2 screenshots.

Browser: Chrome, v45.0.24...
Server: Synology DS415+ with fix IP, port 51042 installed.
In this server, the root www directory is "web" as default and I created a new "www" subfolder, the 3 files are in this. The 51042 port is directed to this, so when I open the (IP):51042/index.html, the program's screen comes up.
But when I cheks the console in the browser, I see the error message.

What can be the problem....? My email is [email protected]

Thank you very much in advance!! :)

Zoltan from Sweden
 

Attachments

  • Archive.zip
    155.2 KB · Views: 473
  • screen03.zip
    120.4 KB · Views: 463

Zoltan Dinya

Member
Licensed User
Longtime User
When I use : http://192.168.1.145/Hello/ the calculate button doesn't work.
When I use : http://192.168.1.145:51042/ the calculate button does work.
Why?
And how can I stop the service?
How do I start the service at a hostingprovider after uploading the files by ftp?

I could fix the calculate buttons problem but only on my own computer. First in B4J, you compile and start the little server software, which is invisible, but works. And after that you switches to your web browser, and 127.0.0.1:51042/index.html
I have Chrome (the actual v45) and it works fine on that!

The question is how can I transport this to a real web-server... I don´t have VPS to run the .jar file, and it is expensive to have a service-provider contract only for this. But I have a Synology DS415+ NAS with fix IP, and I managed to install and setup TOMCAT 7 on it. But it can accept only .war files (is this correct?). With java, I can produce .war packages, I have tested it. Question is, what must I pack into the .war from the project folder? There is: FILES and OBJECTS (subfolders: bin, logs, shell, src, www) and a few files.

Can anyobody write a list about the file, which must be packaged?
 

jinyistudio

Well-Known Member
Licensed User
Longtime User
Hi

Could you share some snipper code about how to interact bootstrap with B4J ?
 

besoft

Active Member
Licensed User
Longtime User
hi,

The head of the index.html file, I added:

B4X:
  <link href="css/bootstrap.min.css" rel="stylesheet">
 <script src="js/bootstrap.min.js"></script>


Then I used the link to adding the necessary elements.

I'm Bootstrap library copied to the local folder because in my target computer can not access the Internet.

Another example from the index.html file:
B4X:
<style>
.jumbotron {
    background-color: #089B23; /* green */
    color: #ffffff;
    padding: 5px 25px;
    font-family: "Lucida Sans", sans-serif;
}
  .bg-grey {
      background-color: #f6f6f6;
  }
  .container-fluid {
      padding: 10px 10px;
  }
   .container-fluid_buttons {
      padding: 5px 20px;
  }
    .con_tabela {
    padding: 10px 0px;
  }
    .btn-group-vertical {
      padding: 20px 10px;
  }

  th {
    text-align: center;
}

td.color  {
    color: green;
    font-weight: bold;
}
td.color1  {
    color: red;
    font-weight: bold;
}
.navbar-inverse  {
    background-color: #089B23; /* green */
    color: #FFFFFF;
    padding: 10px 25px;
    font-family: "Lucida Sans", sans-serif;
}
</style>
 

Eugenio

Member
Licensed User
Longtime User
Hello!

I'm trying to put the example WebAppHelloWorld to work on my site.

Locally it works perfectly.

Localhost: 51042

I made an upload of the complete www folder to my site, but when access example: http://www.teste.com.br/www/index.html

Displays the standard page of WebAppHelloWorld app but does not perform the calculation.

How do I access? http://www.teste.com.br/www:51042?

So also does not work.

Does anyone could give me some help?

Thank you very much!
 

Jose Cadenas

Member
Licensed User
Longtime User
i can send response to one function

Sub btnCalc_Click (Params AsMap)
Dim ft2 AsFuture = text2.GetVal
Dim ft1 AsFuture = text1.GetVal
If IsNumber(ft1.Value) AND IsNumber(ft2.Value) Then
function response('hola mundo')
Else
function response('X')
End If
End Sub

<script>
//connect to the web socket when the pageis ready.
$( document ).ready(function() {
b4j_connect("/ws");});

function response(resp){
if (resp=='X'){
.....................................
}else{
alert(resp);
.....................................
}
}
</script>
 
Top