Wish HttpServer SendBytes method

warwound

Expert
Licensed User
Longtime User
I am using the HttpServer library and want to create JPG and/or PNG images on the fly and return them from the HttpServer HandleRequest event handling sub.

The ServletResponse object has SendFile and SendString methods - i think i need a SendBytes method.
This is my HandleRequest sub:

B4X:
Sub HttpServer1_HandleRequest (Request As ServletRequest, Response As ServletResponse)
   Dim Paths() As String=Regex.Split("/", Request.RequestURI)
   
   If Paths.Length=5 AND Paths(1)="tile" Then
     '   a tile request to serve
     Dim Zoom As Int=Paths(2)
     Dim TileX As Int=Paths(3)
     Dim Temp() As String=Regex.Split("\.", Paths(4))
     Dim TileY As Int=Temp(0)
     
     Dim TileType As String="PNG"
     If Temp(1)="jpg" Then
       TileType="JPEG"
     End If
     
     Dim North As Double=Mercator1.YToLat((TileY*256)-CIRCLE_RADIUS, Zoom)
     Dim South As Double=Mercator1.YToLat(((TileY+1)*256)+CIRCLE_RADIUS, Zoom)
     Dim West As Double=Mercator1.XToLon((TileX*256)-CIRCLE_RADIUS, Zoom)
     Dim East As Double=Mercator1.XToLon(((TileX+1)*256)+CIRCLE_RADIUS, Zoom)
     
     Dim SpatialiteStatement As Spatialite_Stmt
     SpatialiteStatement=SpatialiteDatabase.Prepare("SELECT X(Geometry) AS Longitude, Y(Geometry) AS Latitude FROM "&TABLE_NAME&" WHERE MBRWithin(Geometry, BuildMBR(?, ?, ?, ?, ?));")   '   ORDER BY?
     
     SpatialiteStatement.BindDouble(1, West)
     SpatialiteStatement.BindDouble(2, North)
     SpatialiteStatement.BindDouble(3, East)
     SpatialiteStatement.BindDouble(4, South)
     SpatialiteStatement.BindInt(5, SRID)
     
     Dim Tile As Bitmap
     Tile.InitializeMutable(256, 256)
     Dim Canvas1 As Canvas
     Canvas1.Initialize2(Tile)
     
     Dim X As Int
     Dim Y As Int
     Dim Latitude As Double
     Dim Longitude As Double
     
     Dim Count As Int=0
     Do While SpatialiteStatement.Step
       Count=Count+1
       Latitude=SpatialiteStatement.ColumnDouble(1)
       Longitude=SpatialiteStatement.ColumnDouble(0)
       X=Mercator1.LonToX(Longitude, Zoom)-(TileX*256)
       Y=Mercator1.LatToY(Latitude, Zoom)-(TileY*256)
       Canvas1.DrawCircle(X, Y, CIRCLE_RADIUS, CIRCLE_COLOR, CIRCLE_FILL, CIRCLE_STROKE_WIDTH)
     Loop
     Log("Count: "&Count)
     
     ' here i have to save the image to a temp file
     TileId=TileId+1
     Dim TempFileName As String="tile-"&TileId&"."&Temp(1)
     Dim TempFile As OutputStream=File.OpenOutput(File.DirInternalCache, TempFileName, False)
     Tile.WriteToStream(TempFile, 100, TileType)
     TempFile.Close
     
     If TileType="PNG" Then
       Response.SetContentType("image/png")
     Else
       Response.SetContentType("image/jpeg")
     End If
     
     Response.SendFile(File.DirInternalCache, TempFileName)
     File.Delete(File.DirInternalCache, TempFileName)
     
     Return
     
   End If
   
   Response.SetContentType("text/html")
   Response.SendString("No valid tile request received")
End Sub

So i have a Bitmap named Tile that i wish to serve as a JPG or PNG image, currently i'm writing it to a file and using the ServletResponse SendFile method to serve it.
Ideally i'd be able to use WriteToStream to write the image to an OutputStream then send the OutputStream bytes with no need for the temporary file.

Is this possible - can a SendBytes method be added to the ServletResponse?

Thanks.

Martin.
 

warwound

Expert
Licensed User
Longtime User
Ok using a temp file is acceptable.
But i have a problem writing the temp file to File.DirDefaultExternal on my Galaxy S3 running android 4.1.2.
This is the code that creates the temp file and returns the Bitmap as the server response:

B4X:
TileId=TileId+1
Dim TempFileName As String="tile-"&TileId&"."&FileExtension
Dim TempFile As OutputStream=File.OpenOutput(File.DirDefaultExternal, TempFileName, False)
Tile.WriteToStream(TempFile, TILE_COMPRESSION_LEVEL, TileType)
TempFile.Close
Response.SetContentType(ContentType)
Response.SendFile(File.DirDefaultExternal, TempFileName)
File.Delete(File.DirDefaultExternal, TempFileName)

TileId is a process global integer, it's used to ensure each temp file has a unique filename.

On my S3 this always fails with many exceptions of this type:

2014-01-03 08:54:03.275:WARN::/tiles/10/513/333.png
java.lang.RuntimeException: java.io.IOException: read failed: EIO (I/O error)
at anywheresoftware.b4a.objects.Servlet.handleRequest(Servlet.java:105)
at anywheresoftware.b4a.objects.Servlet.doGet(Servlet.java:73)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:538)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:478)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:937)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:406)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:871)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:110)
at org.eclipse.jetty.server.Server.handle(Server.java:346)
at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:589)
at org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:1048)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:601)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:214)
at org.eclipse.jetty.server.HttpConnection.handle(HttpConnection.java:411)
at org.eclipse.jetty.server.nio.BlockingChannelConnector$BlockingChannelEndPoint.run(BlockingChannelConnector.java:289)
at org.eclipse.jetty.util.thread.QueuedThreadPool$1.run(QueuedThreadPool.java:529)
at java.lang.Thread.run(Thread.java:856)
Caused by:
java.io.IOException: read failed: EIO (I/O error)
at libcore.io.IoBridge.read(IoBridge.java:442)
at java.io.FileInputStream.read(FileInputStream.java:179)
at java.io.BufferedInputStream.read(BufferedInputStream.java:304)
at java.io.InputStream.read(InputStream.java:163)
at anywheresoftware.b4a.objects.streams.File.Copy2(File.java:336)
at anywheresoftware.b4a.objects.Servlet.handleRequest(Servlet.java:100)
at anywheresoftware.b4a.objects.Servlet.doGet(Servlet.java:73)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:538)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:478)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:937)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:406)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:871)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:110)
at org.eclipse.jetty.server.Server.handle(Server.java:346)
at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:589)
at org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:1048)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:601)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:214)
at org.eclipse.jetty.server.HttpConnection.handle(HttpConnection.java:411)
at org.eclipse.jetty.server.nio.BlockingChannelConnector$BlockingChannelEndPoint.run(BlockingChannelConnector.java:289)
at org.eclipse.jetty.util.thread.QueuedThreadPool$1.run(QueuedThreadPool.java:529)
at java.lang.Thread.run(Thread.java:856)

Looks as though the code fails to write the temp file and then an exception is thrown when it tries to read the non-existent file.
The S3 has an SD card inserted and there's plenty of free space on both built in external memory and the SD card.
Using a file explorer i find no temp files in the built in external memory File.DirDefaultExternal location or the same location on SD card.

The same code works perfectly on an old HTC Desire S.

Saving the temp file to File.DirInternal or File.DirInternalCache works on all devices tested so far.

Any idea why the S3 fails to write the temp file?

Martin.
 

warwound

Expert
Licensed User
Longtime User
No i'm not compiling to a library.

I have a service module running the HttpServer library and in the HttpServer library HandleRequest event i (try to) write this temp file.
The manifest shows that the required 'android.permission.WRITE_EXTERNAL_STORAGE' permission has been added.

As i said it works on an old HTC Desire S - which has no built in external memory.

I just tested the code on my Tab2 - again it fails with the same exceptions as on the S3.
On the S3 and Tab2 it seems as though the temp file isn't written to external memory.
Both the S3 and Tab2 have built in external memory and both the S3 and Tab2 have plenty of available space on both built in external memory and SD card.

Martin.
 

warwound

Expert
Licensed User
Longtime User
I just had a thought that might be relevant.

The service module that contains the HttpServer and fails to write the temp tile does successfully copy a database file from Assets to DirDefaultExternal in Service_Start.
That File operation works yet in the same service module writing the temp file fails in the HttpServer HandleRequest event.

Martin.
 

warwound

Expert
Licensed User
Longtime User
Still no success.

I updated my code that creates the temp file, calling the OutputStream Flush method before calling it's Close method.
I also added a Log statement to log the name of the temp file i'm trying to create.
And then i added a little code to create a plain text file - but only to create the text file once:

B4X:
TileId=TileId+1
Dim TempFileName As String="tile-"&TileId&"."&FileExtension

Log("TempFileName: "&TempFileName&", TileType: "&TileType)

Dim OutputStream1 As OutputStream=File.OpenOutput(File.DirDefaultExternal, TempFileName, False)
Tile.WriteToStream(OutputStream1, TILE_COMPRESSION_LEVEL, TileType)
OutputStream1.Flush
OutputStream1.Close
Response.SetContentType(ContentType)
Response.SendFile(File.DirDefaultExternal, TempFileName)
File.Delete(File.DirDefaultExternal, TempFileName)

If TileId=2 Then
   File.WriteString(File.DirDefaultExternal, "debug.txt", "some text here")
End If

The log shows a valid file name for my temp file (and a valid TileType of 'PNG'), but still the same exception (file not found) when i try to open the temp file:

LogCat connected to: c080813ee7df721
--------- beginning of /dev/log/system
--------- beginning of /dev/log/main
Static storage paths aren't available from AID_SYSTEM
java.lang.Throwable
at android.os.Environment.throwIfSystem(Environment.java:637)
at android.os.Environment.getExternalStorageDirectory(Environment.java:316)
at com.android.settings.nearby.MountReceiver.onReceive(MountReceiver.java:105)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2441)
at android.app.ActivityThread.access$1600(ActivityThread.java:150)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:175)
at android.app.ActivityThread.main(ActivityThread.java:5279)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(Native Method)
Static storage paths aren't available from AID_SYSTEM
java.lang.Throwable
at android.os.Environment.throwIfSystem(Environment.java:637)
at android.os.Environment.getExternalStorageDirectory(Environment.java:316)
at com.wssnps.smlModelDefine.Feature_Init(smlModelDefine.java:352)
at com.wssnps.smlNpsReceiver.onReceive(smlNpsReceiver.java:512)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2441)
at android.app.ActivityThread.access$1600(ActivityThread.java:150)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:175)
at android.app.ActivityThread.main(ActivityThread.java:5279)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(Native Method)
Static storage paths aren't available from AID_SYSTEM
java.lang.Throwable
at android.os.Environment.throwIfSystem(Environment.java:637)
at android.os.Environment.getExternalStorageDirectory(Environment.java:316)
at com.android.MtpApplication.MtpReceiver.onReceive(MtpReceiver.java:1137)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2441)
at android.app.ActivityThread.access$1600(ActivityThread.java:150)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:175)
at android.app.ActivityThread.main(ActivityThread.java:5279)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(Native Method)
Static storage paths aren't available from AID_SYSTEM
java.lang.Throwable
at android.os.Environment.throwIfSystem(Environment.java:637)
at android.os.Environment.getExternalStorageDirectory(Environment.java:316)
at com.samsung.SMT.SamsungTTSPreference.<clinit>(SamsungTTSPreference.java:43)
at com.samsung.SMT.SamsungTTSService.onCreate(SamsungTTSService.java:438)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2594)
at android.app.ActivityThread.access$1700(ActivityThread.java:150)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1368)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:175)
at android.app.ActivityThread.main(ActivityThread.java:5279)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(Native Method)
Static storage paths aren't available from AID_SYSTEM
java.lang.Throwable
at android.os.Environment.throwIfSystem(Environment.java:637)
at android.os.Environment.getExternalStorageDirectory(Environment.java:316)
at com.android.MtpApplication.MtpReceiver.onReceive(MtpReceiver.java:1137)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2441)
at android.app.ActivityThread.access$1600(ActivityThread.java:150)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:175)
at android.app.ActivityThread.main(ActivityThread.java:5279)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(Native Method)
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
MapFragment1_Ready
B4A TileServer started
** Service (tileserver) Create **
2014-01-03 12:39:48.718:INFO::jetty-7.x.y-SNAPSHOT
2014-01-03 12:39:49.440:INFO::started o.e.j.s.ServletContextHandler{/,null}
2014-01-03 12:39:49.543:INFO::Started [email protected]:5555 STARTING
org.eclipse.jetty.server.Server@42138f50
** Service (tileserver) Start **
TempFileName: tile-1.png, TileType: PNG
Places count: 81, tile creation took 1060 ticks
2014-01-03 12:39:51.501:WARN::/tiles/10/512/336.png
java.lang.RuntimeException: java.io.IOException: read failed: ENOENT (No such file or directory)
at anywheresoftware.b4a.objects.Servlet.handleRequest(Servlet.java:105)
at anywheresoftware.b4a.objects.Servlet.doGet(Servlet.java:73)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:538)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:478)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:937)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:406)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:871)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:110)
at org.eclipse.jetty.server.Server.handle(Server.java:346)
at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:589)
at org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:1048)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:601)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:214)
at org.eclipse.jetty.server.HttpConnection.handle(HttpConnection.java:411)
at org.eclipse.jetty.server.nio.BlockingChannelConnector$BlockingChannelEndPoint.run(BlockingChannelConnector.java:289)
at org.eclipse.jetty.util.thread.QueuedThreadPool$1.run(QueuedThreadPool.java:529)
at java.lang.Thread.run(Thread.java:856)
Caused by:
java.io.IOException: read failed: ENOENT (No such file or directory)
at libcore.io.IoBridge.read(IoBridge.java:442)
at java.io.FileInputStream.read(FileInputStream.java:179)
at java.io.BufferedInputStream.read(BufferedInputStream.java:304)
at java.io.InputStream.read(InputStream.java:163)
at anywheresoftware.b4a.objects.streams.File.Copy2(File.java:336)
at anywheresoftware.b4a.objects.Servlet.handleRequest(Servlet.java:100)
at anywheresoftware.b4a.objects.Servlet.doGet(Servlet.java:73)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:538)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:478)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:937)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:406)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:871)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:110)
at org.eclipse.jetty.server.Server.handle(Server.java:346)
at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:589)
at org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:1048)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:601)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:214)
at org.eclipse.jetty.server.HttpConnection.handle(HttpConnection.java:411)
at org.eclipse.jetty.server.nio.BlockingChannelConnector$BlockingChannelEndPoint.run(BlockingChannelConnector.java:289)
at org.eclipse.jetty.util.thread.QueuedThreadPool$1.run(QueuedThreadPool.java:529)
at java.lang.Thread.run(Thread.java:856)
Caused by:
libcore.io.ErrnoException: read failed: ENOENT (No such file or directory)
at libcore.io.Posix.readBytes(Native Method)
at libcore.io.Posix.read(Posix.java:123)
at libcore.io.BlockGuardOs.read(BlockGuardOs.java:149)
at libcore.io.IoBridge.read(IoBridge.java:432)
at java.io.FileInputStream.read(FileInputStream.java:179)
at java.io.BufferedInputStream.read(BufferedInputStream.java:304)
at java.io.InputStream.read(InputStream.java:163)
a
Message longer than Log limit (4000). Message was truncated.

Notice the very start of the log?
Every time i connect the Tab2 to B4A IDE i get these Static storage paths aren't available from AID_SYSTEM error messages.
But i don't get these error messages when i connect my S3 - only with the Tab2.

The 'debug.txt' file is successfully created when the server creates it's second tile - that's when my variable TileId is 2.
So using File.DirDefaultExternal, File.WriteString is working but not File.OpenOutput.

EDIT: Just leaving the service running and spitting out lots and lots of similar exceptions i noticed this one:

2014-01-03 13:04:18.250:WARN::/tiles/10/511/334.png
java.lang.RuntimeException: java.lang.InterruptedException
at anywheresoftware.b4a.objects.Servlet.handleRequest(Servlet.java:105)
at anywheresoftware.b4a.objects.Servlet.doGet(Servlet.java:73)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:538)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:478)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:937)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:406)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:871)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:110)
at org.eclipse.jetty.server.Server.handle(Server.java:346)
at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:589)
at org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:1048)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:601)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:214)
at org.eclipse.jetty.server.HttpConnection.handle(HttpConnection.java:411)
at org.eclipse.jetty.server.nio.BlockingChannelConnector$BlockingChannelEndPoint.run(BlockingChannelConnector.java:289)
at org.eclipse.jetty.util.thread.QueuedThreadPool$1.run(QueuedThreadPool.java:529)
at java.lang.Thread.run(Thread.java:856)
Caused by:
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedNanos(AbstractQueuedSynchronizer.java:1014)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1302)
at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:248)
at anywheresoftware.b4a.objects.Servlet.handleRequest(Servlet.java:92)
at anywheresoftware.b4a.objects.Servlet.doGet(Servlet.java:73)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:538)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:478)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:937)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:406)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:871)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:110)
at org.eclipse.jetty.server.Server.handle(Server.java:346)
at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:589)
at org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:1048)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:601)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:214)
at org.eclipse.jetty.server.HttpConnection.handle(HttpConnection.java:411)
at org.eclipse.jetty.server.nio.BlockingChannelConnector$BlockingChannelEndPoint.run(BlockingChannelConnector.java:289)
at org.eclipse.jetty.util.thread.QueuedThreadPool$1.run(QueuedThreadPool.java:529)
at java.lang.Thread.run(Thread.java:856)

Is the problem related to the temp file creation (Bitmap to PNG to OutputStream to File) happening in a non UI Thread?

Martin.
 

warwound

Expert
Licensed User
Longtime User
:) Thanks - that was exactly the problem.

Now i have another problem - how to delete the temp files my tile server will create?
Things aren't happening in a synchronous order.
When, after calling Response.SendFile, can i be sure that the file has been served and can now be deleted?

I don't want the external memory to accumulate many redundant temporary files.
IDEA! Maybe if i implement some sort of caching of created tiles i can manage all the tiles (temp files) elsewhere in the service module and avoid accumulating too many (as well as avoiding re-creating tiles that have already recently been created)...

I'll have to think about maintaining a tile cache.

But i think my original request is still valid.
A ServletResponse SendBytes method would do the exact thing i need to do and avoid any asynchronous timing issues with temp files.

Martin.
 

warwound

Expert
Licensed User
Longtime User
Yeah the temp file solution is far from elegant, all that's needed is a new ServletResponse method:

B4X:
public void SendBytes(byte[] Bytes){
   response=Bytes;
   res.setContentLength(response.length);
}

Martin.
 
Top