This is an old example. Better use B4XSerializator to serialize objects.
One of the nice things about using B4J server as the backend of B4A applications is that you can send and receive objects such as custom types and collections of custom types instead of working with bytes or strings.
In this example we have two custom types:
These types are declared both in the server and the client applications.
The client will send a list of Orders and the server will return an OrderResult object. The serialization of the objects is done with RandomAccessFile.WriteObject / ReadObject. It supports all primitive types, custom types, arrays and collections. Note that Bitmaps are not supported.
Client Code
Server code
Main module:
OrderHander class:
Note that the server writes the object into a temporary buffer. The buffer must be large enough in order to hold the serialized data. You can check raf.CurrentPosition after writing the object to get an estimation of the required size. Another option is to use a temporary file as done in the client. However for this to work properly you need to set the handler to run in single threaded mode.
Note that you will see the following message in the logs:
You can ignore it. It happens on the first time that a type with a different package is discovered.
One of the nice things about using B4J server as the backend of B4A applications is that you can send and receive objects such as custom types and collections of custom types instead of working with bytes or strings.
In this example we have two custom types:
B4X:
Type Order(ProductKey As String, Amount As Int, Comment As String)
Type OrderResult(NumberOfOrders As Int, Success As Boolean)
These types are declared both in the server and the client applications.
The client will send a list of Orders and the server will return an OrderResult object. The serialization of the objects is done with RandomAccessFile.WriteObject / ReadObject. It supports all primitive types, custom types, arrays and collections. Note that Bitmaps are not supported.
Client Code
B4X:
Sub Process_Globals
Type Order(ProductKey As String, Amount As Int, Comment As String)
Type OrderResult(NumberOfOrders As Int, Success As Boolean)
Private raf As RandomAccessFile
'server link
Private link As String = "http://192.168.0.100:51042/order"
End Sub
Sub Activity_Create(FirstTime As Boolean)
If FirstTime Then
raf.Initialize(File.DirInternal, "temp", False)
End If
Dim Orders As List
Orders.Initialize
For i = 1 To 20
Dim o As Order
o.Initialize
o.ProductKey = "Item #" & i
o.Amount = 7
o.Comment = "abcdef"
Orders.Add(o)
Next
SendObject(Orders)
End Sub
Sub SendObject (Obj As Object)
raf.WriteObject(Obj, True, 0)
Dim size As Int = raf.CurrentPosition
Dim data(size) As Byte
raf.CurrentPosition = 0
Do While raf.CurrentPosition < size
raf.ReadBytes(data, raf.CurrentPosition, size - raf.CurrentPosition, _
raf.CurrentPosition)
Loop
Dim j As HttpJob
j.Initialize("send object", Me)
j.PostBytes(link, data)
End Sub
Sub ReadObject (In As InputStream) As Object
Dim out As OutputStream
out.InitializeToBytesArray(0)
File.Copy2(In, out)
Dim raf2 As RandomAccessFile
raf2.Initialize3(out.ToBytesArray, False)
Dim res As Object = raf2.ReadObject(0)
raf2.Close
Return res
End Sub
Sub JobDone(j As HttpJob)
If j.Success Then
Dim result As OrderResult = ReadObject(j.GetInputStream)
Log(result)
Else
Log("Error: " & j.ErrorMessage)
End If
j.Release
End Sub
Server code
Main module:
B4X:
Sub Process_Globals
Type Order(ProductKey As String, Amount As Int, Comment As String)
Type OrderResult(NumberOfOrders As Int, Success As Boolean)
Private srvr As Server
End Sub
Sub AppStart (Args() As String)
srvr.Initialize("")
srvr.Port = 51042
srvr.AddHandler("/order", "OrderHandler", False)
srvr.Start
StartMessageLoop
End Sub
OrderHander class:
B4X:
Sub Class_Globals
'The buffer must be large enough to hold the result object.
Private bufferSize As Int = 1000
End Sub
Public Sub Initialize
End Sub
Sub Handle(req As ServletRequest, resp As ServletResponse)
Dim orders As List = ReadObject(req.InputStream)
Dim result As OrderResult
result.Initialize
For Each o As Order In orders
'work with the order
Log(o.ProductKey & ", " & o.Amount & ", " & o.Comment)
result.NumberOfOrders = result.NumberOfOrders + 1
Next
result.Success = True
SendObject(result, resp.OutputStream)
End Sub
Sub ReadObject (In As InputStream) As Object
Dim out As OutputStream
out.InitializeToBytesArray(0)
File.Copy2(In, out)
Dim raf2 As RandomAccessFile
raf2.Initialize3(out.ToBytesArray, False)
Dim res As Object = raf2.ReadObject(0)
raf2.Close
Return res
End Sub
Sub SendObject (Obj As Object, Out As OutputStream)
Dim raf As RandomAccessFile
Dim buffer(bufferSize) As Byte
raf.Initialize3(buffer, False)
raf.WriteObject(Obj, True, 0)
Out.WriteBytes(buffer, 0, raf.CurrentPosition)
End Sub
Note that the server writes the object into a temporary buffer. The buffer must be large enough in order to hold the serialized data. You can check raf.CurrentPosition after writing the object to get an estimation of the required size. Another option is to use a temporary file as done in the client. However for this to work properly you need to set the handler to run in single threaded mode.
Note that you will see the following message in the logs:
Class not found: b4a.example.main$_order, trying: b4j.example.main$_order
You can ignore it. It happens on the first time that a type with a different package is discovered.
Last edited: