Reputation: 377
An external library uses java.io.Writer
interface for some kind of output, and at the moment I use StringWriter
to buffer all output and then Ok(writer.toString)
. But I'd want to avoid buffering and to stream data supplied by Writer
.
How to craft a Play Enumerator
based on java.io.Writer
?
Upvotes: 0
Views: 143
Reputation: 377
With help of faissalb I have got this final working fragment (it is streaming of FreeMarker output, but can be used at any Writer
-expected case, of course):
class FltWriter(channel: Concurrent.Channel[Array[Byte]]) extends java.io.Writer {
def write(cs: Array[Char], start: Int, len: Int): Unit = channel.push(new String(cs, start, len).getBytes("UTF-8"))
def flush: Unit = channel.end
def close: Unit = channel.eofAndEnd
}
def e(tpl: String, data: Map[String, Any], config: Configuration = cfg)(implicit ec: ExecutionContext) =
Concurrent.unicast[Array[Byte]] { channel => config.getTemplate(tpl).process(data, new FltWriter(channel)) }
At the case (that is FreeMarker output) used flush
is obligatory.
You see, channel
has moved into Writer
constructor resulting in immutable code.
Upvotes: 0
Reputation: 1749
You can implement your own writer that uses a Concurrent.Channel to push data to an enumerator, let's talk code:
class MyWriter extends java.io.Writer{
var channel : Concurent.Channel
def write(x:Array[Char], s:Int, e:Int) = {
channel.push(x)
}
def close() = {
channel.end()
}
def flush() = {
}
}
// every time writer.write is used it will push data to the enumeratr
var writer = new YourWriter();
val enumerator:Enumerator[Array[Char]] = Concurrent.unicast[Array[Char]](channel => {writer.channel = channel})
Upvotes: 1