B4J Tutorial [Server] Send and receive objects

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:
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:

Roberto P.

Well-Known Member
Licensed User
Hi

simple question: what are the parameters to connect to a sqlserver DB instead of SqlLite?

#AdditionalJar: Sqlite-jdbc-3.7.2

SQL1.InitializeSQLite (File.DirApp, "db.db", True)

regards
 

MbedAndroid

Active Member
Licensed User
this happens suddenly after no changes to code
it will be invoked by starting the server
Someone has a idea why?
Resetting the rasp?
Dont got this error local on the pc
Internet works fine, got the SSH remote control, no problem
1
1
version1.02
0
2015-11-16 15:51:22.832:INFO::main: Logging initialized @6602ms
2015-11-16 15:51:23.409:INFO:eek:ejs.Server:main: jetty-9.1.z-SNAPSHOT
2015-11-16 15:51:23.547:WARN:eek:ejh.MimeTypes:main: java.util.MissingResourceException: Can't find bundle for base name org/eclipse/jetty/http/encoding, locale nl_NL
2015-11-16 15:51:23.671:INFO:eek:ejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@ea639{/,file:/home/pi/tempjars/www,AVAILABLE}
2015-11-16 15:51:23.683:WARN:eek:ejuc.AbstractLifeCycle:main: FAILED org.eclipse.jetty.server.NCSARequestLog@ac6e3: java.io.IOException: Cannot write log directory /home/pi/tempjars/logs
java.io.IOException: Cannot write log directory /home/pi/tempjars/logs
at org.eclipse.jetty.util.RolloverFileOutputStream.setFile(RolloverFileOutputStream.java:219)
at org.eclipse.jetty.util.RolloverFileOutputStream.<init>(RolloverFileOutputStream.java:166)
at org.eclipse.jetty.server.NCSARequestLog.doStart(NCSARequestLog.java:228)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.server.handler.RequestLogHandler.doStart(RequestLogHandler.java:131)
at org.eclipse.jetty.util.component.AbstractLifeCycle
.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.server.Server.start(Server.java:358)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.server.Server.doStart(Server.java:325)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at anywheresoftware.b4j.object.ServerWrapper.Start(ServerWrapper.java:151)
at b4j.example.main._appstart(main.java:109)
at sun.reflect.NativeMethodAcce
ssorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:84)
at b4j.example.main.main(main.java:29)
2015-11-16 15:51:23.697:WARN:eek:ejuc.AbstractLifeCycle:main: FAILED org.eclipse.jetty.server.handler.RequestLogHandler@1be98f5: java.io.IOException: Cannot write log directory /home/pi/tempjars/logs
java.io.IOException: Cannot write log directory /home/pi/tempjars/logs
at org.eclipse.jetty.util.RolloverFileOutputStream.setFile(RolloverFileOutputStream.java:219)
at org.eclipse.jetty.util.RolloverFileOutputStream.<init>(RolloverFileOutputStream.java:166)
at org.eclipse.jetty.server.NCSARequestLog.doStart(NCSARequestLog.java:228)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.server.handler.RequestLogHandler.doStart(RequestLogHandler.java:131)
at org.eclipse.jetty.util.component.Abst
ractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.server.Server.start(Server.java:358)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.server.Server.doStart(Server.java:325)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at anywheresoftware.b4j.object.ServerWrapper.Start(ServerWrapper.java:151)
at b4j.example.main._appstart(main.java:109)
at sun.reflect.Nat
iveMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:84)
at b4j.example.main.main(main.java:29)
2015-11-16 15:51:23.704:WARN:eek:ejuc.AbstractLifeCycle:main: FAILED org.eclipse.jetty.server.handler.HandlerCollection@1adae5d: java.io.IOException: Cannot write log directory /home/pi/tempjars/logs
java.io.IOException: Cannot write log directory /home/pi/tempjars/logs
at org.eclipse.jetty.util.RolloverFileOutputStream.setFile(RolloverFileOutputStream.java:219)
at org.eclipse.jetty.util.RolloverFileOutputStream.<init>(RolloverFileOutputStream.java:166)
at org.eclipse.jetty.server.NCSARequestLog.doStart(NCSARequestLog.java:228)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.server.handler.RequestLogHandler.doStart(RequestLogHandler.java:131)
at org.eclipse.jetty.util.component.Abst
ractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.server.Server.start(Server.java:358)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.server.Server.doStart(Server.java:325)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at anywheresoftware.b4j.object.ServerWrapper.Start(ServerWrapper.java:151)
at b4j.example.main._appstart(main.java:109)
at sun.reflect.Nat
iveMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:84)
at b4j.example.main.main(main.java:29)
2015-11-16 15:51:23.894:INFO:eek:ejs.ServerConnector:main: Started ServerConnector@1b6a447{HTTP/1.1}{0.0.0.0:4300}
2015-11-16 15:51:23.897:WARN:eek:ejuc.AbstractLifeCycle:main: FAILED org.eclipse.jetty.server.Server@19b4d0f: java.io.IOException: Cannot write log directory /home/pi/tempjars/logs
java.io.IOException: Cannot write log directory /home/pi/tempjars/logs
at org.eclipse.jetty.util.RolloverFileOutputStream.setFile(RolloverFileOutputStream.java:219)
at org.eclipse.jetty.util.RolloverFileOutputStream.<init>(RolloverFileOutputStream.java:166)
at org.eclipse.jetty.server.NCSARequestLog.doStart(NCSARequestLog.java:228)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.server.handler.RequestLogHandler.doStart(RequestLogHandler.java:131)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start
(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.server.Server.start(Server.java:358)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.server.Server.doStart(Server.java:325)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at anywheresoftware.b4j.object.ServerWrapper.Start(ServerWrapper.java:151)
at b4j.example.main._appstart(main.java:109)
at sun.reflect.NativeMethodAccessorIm
pl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:84)
at b4j.example.main.main(main.java:29)
main._appstart (java line: 109)
java.io.IOException: Cannot write log directory /home/pi/tempjars/logs
at org.eclipse.jetty.util.RolloverFileOutputStream.setFile(RolloverFileOutputStream.java:219)
at org.eclipse.jetty.util.RolloverFileOutputStream.<init>(RolloverFileOutputStream.java:166)
at org.eclipse.jetty.server.NCSARequestLog.doStart(NCSARequestLog.java:228)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.server.handler.RequestLogHandler.doStart(RequestLogHandler.java:131)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doS
tart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.server.Server.start(Server.java:358)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.server.Server.doStart(Server.java:325)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at anywheresoftware.b4j.object.ServerWrapper.Start(ServerWrapper.java:151)
at b4j.example.main._appstart(main.java:109)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAc
cessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:84)
at b4j.example.main.main(main.java:29)
main.main (java line: 29)
java.lang.RuntimeException: java.io.IOException: Cannot write log directory /home/pi/tempjars/logs
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:114)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:84)
at b4j.example.main.main(main.java:29)
Caused by: java.io.IOException: Cannot write log directory /home/pi/tempjars/logs
at org.eclipse.jetty.util.RolloverFileOutputStream.setFile(RolloverFileOutputStream.java:219)
at org.eclipse.jetty.util.RolloverFileOutputStream.<init>(RolloverFileOutputStream.java:166)
at org.eclipse.jetty.server.NCSARequestLog.doStart(NCSARequestLog.java:228)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.server.handler.RequestLogHandler.doStart(RequestLogHa
ndler.java:131)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.server.Server.start(Server.java:358)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.server.Server.doStart(Server.java:325)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at anywheresoftware.b4j.object.ServerWrapper.Start(ServerWrapper.java:151)
at b4j.
example.main._appstart(main.java:109)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)
... 2 more
 

MbedAndroid

Active Member
Licensed User
mmm
got the same with the example
will reset the rasp first, see if that helps
remember i updated and upgraded yesterday rasbian, it might be the problem
 
Top