Scala: Receiving Server-Sent-Events
Asked Answered
C

3

8

Set-up:

A project I am working on has a pub/sub server with an HTTP interface. Subscription works by accepting server-sent-events.

curl -X GET server:port/topics/news

which will be pushed whenever a message is published to the given topic URL

curl -X PUT server:port/topics/news -d "Politician Lies!"

Problem:

I have a scala project which needs to subscribe to this pub/sub server. The Play! framework is able to handle this by using PlayWS with Enumeratee + Iteratee. Unfortunately, the PlayWS library requires that a Play! Application is in scope and I am not using Play. Is there a library (with minimal dependancies) I can use which allows me to accept server-sent-events? I'll need at least one working example in order to get started.

I have a preference for scala libraries but I'm willing to accept a Java solution if I have to.

Conceivable answered 16/5, 2014 at 19:22 Comment(0)
L
3

You have several possibilities:

In Play 2.3, the WS library is now a separate library, so that should help. RC2 is already available

Alternatively, you could depend on Play 2.x and use a StaticApplication like so:

val application = new StaticApplication(new java.io.File("."))

This will essentially bootstrap a Play application, and from there on you can use the WS library as usual

Leilaleilah answered 26/5, 2014 at 10:13 Comment(1)
This looks promising. I had some trouble using the PlayWS 2.2 library before creating this question. Are you able to create a self-contained example of using PlayWS to accept SSE?Conceivable
C
4

I've accepted Manuel Bernhardt's answer because it led me in the right direction but I feel a full example is important for anyone else with this issue.

I updated my build.sbt file to include PlayWS 2.3 and the Iteratees library.

libraryDependencies ++= Seq(
  "com.typesafe.play" %% "play-ws" % "2.3.0",
  "com.typesafe.play" %% "play-iteratees" % "2.3.0"
)

The WS singleton requires an implicit Play Application to be used (something I don't have or want) so instead I will need to create my own client

val builder = new (com.ning.http.client.AsyncHttpClientConfig.Builder)()
val client = new play.api.libs.ws.ning.NingWSClient(builder.build())

I then create my Iteratee so that I can handle my server-sent-events.

def print = Iteratee.foreach { chunk: Array[Byte] => 
  println(new String(chunk))
}

and finally subscribe to the server

client.url("http://localhost:8080/topics/news").get(_ => print)

Now, when an event is sent

curl -X PUT server:port/topics/news -d "Politician Lies!"

My Scala application will print the received event

data: Politician Lies!
Conceivable answered 1/6, 2014 at 2:0 Comment(0)
L
3

You have several possibilities:

In Play 2.3, the WS library is now a separate library, so that should help. RC2 is already available

Alternatively, you could depend on Play 2.x and use a StaticApplication like so:

val application = new StaticApplication(new java.io.File("."))

This will essentially bootstrap a Play application, and from there on you can use the WS library as usual

Leilaleilah answered 26/5, 2014 at 10:13 Comment(1)
This looks promising. I had some trouble using the PlayWS 2.2 library before creating this question. Are you able to create a self-contained example of using PlayWS to accept SSE?Conceivable
H
2

I'm not aware of other Scala libraries that implement a Server Sent Events client, but the Jersey project has a Java library for Server Sent Events clients (as well as servers). The API does not appear to be very verbose, and appears like it can be nicely wrapped in some code to fit in more idiomatically with Scala.

Hickie answered 26/5, 2014 at 9:38 Comment(2)
I explored this option before making this question. It would require me to write a wrapper but the overhead would be small. +1 but I'm still holding out for a Scala optionConceivable
Issue with artifact javax.ws.rs-api in SBT seems to block usage of this, at the moment: github.com/gradle/gradle/issues/3065Biographical

© 2022 - 2024 — McMap. All rights reserved.