Hi,
I am creating a simple REST API using Scalatra, Async / Futures / Akka support and Swagger.
Basically I need to upload a CSV file to a machine. The server then uses Futures / Akka to schedule doing something with that CSV file at some future time.
Generally this will be called by another machine (hence Swagger), but I want to make it possible for a human to do it as well for test purposes (hence using CSV rather than JSON).
However I was having a lot of trouble getting FileUpload to work. To begin with I thought this was due to Swagger. It did take me a little bit of time to get the Swagger UI to play nice with Scalatra, but that now seems to work.
I think it is AsyncResult that is causing the problem. To demonstrate this I have put together a simplest possible example here
Specifically here
You can see two variants of the same post request, one that uses AsyncResult / Future, the other does not.
If you run the server from SBT:
container:start
You see that the version without the future works fine, but the future version fails with this exception:
java.io.FileNotFoundException: /tmp/jetty-0.0.0.0-8080-webapp-_-any-8266606499060789825.dir/MultiPart1494068154862294142 (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:146)
at org.eclipse.jetty.util.MultiPartInputStreamParser$MultiPart.getInputStream(MultiPartInputStreamParser.java:211)
at org.scalatra.servlet.FileItem.getInputStream(FileUploadSupport.scala:253)
at com.pataniqa.example.MyScalatraServlet$$anonfun$2$$anon$1$$anonfun$3.apply(MyScalatraServlet.scala:61)
at com.pataniqa.example.MyScalatraServlet$$anonfun$2$$anon$1$$anonfun$3.apply(MyScalatraServlet.scala:58)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:41)
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:393)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Strangely though if I keep trying the future version, sometimes it succeeds, but generally it fails?
Is my use of AsyncResult / Future correct?
If it is correct is there is a workaround for this?
Thanks very much for Scalatra, Scalatra Swagger and Akka support.
Mark