New asynchronous features for Play 1.2, continuations and WebSocket

1272 views
Skip to first unread message

Guillaume Bort

unread,
Feb 11, 2011, 8:25:24 AM2/11/11
to play-fr...@googlegroups.com
Hi all,

The whole refactoring for better asynchronism management in Play 1.2,
is almost finished and available in the Play git master.

These new features cover several points I will introduce here:

- Promises
- A new Functional style library (play.libs.F)
- await(…)
- Continuations
- Response streaming
- WebSockets
- Pattern matching

First, it is already possible to achieve asynchronism with Play 1.1
using Java Future and waitFor(...) and suspend(...) controller
methods. However these primitives was not really easy to use. That's
why we've worked on a complete set of new coherent features for Play
1.2.

-- Promises:

In Play 1.2 we introduce Promise that is the Play's custom Future type
(Promise was named Task in previous commits on master) . In fact a
Promise<T> is also a Future<T> so you can use it as a standard Future.
But it has also a very interesting property: the ability to register
callback using onRedeem(…) that will be called as soon as the promised
value is available. It allows the framework to register itself on them
and to reschedule the request invocation as soon as possible.

Promises are used everywhere in Play in place of Future (for Jobs,
WS.async, etc…)

Promises can be combined in several way. For example:

- Promise p = Promise.waitAll(p1, p2, p3)
- Promise p = Promise.waitAny(p1, p2, p3)
- Promise p = Promise.waitEither(p1, p2, p3)

-- play.libs.F:

The Promise type is part of new library (play.libs.F) that introduces
several useful constructs coming from functional programming. These
constructs are used to handle complex cases that I will expose just
later. For those that are accustomed to functional programming we
provide:

- Option<T> (a T value that can be or not set)
- Either<A,B> (contains either a A value or a B value)
- Tuple<A,B> (contains both A and B values)

-- await(…):

So, now when your application code returns values that are not yet
available using a Promise<T>, you want to be able to ask Play to wait
for this promised result to be available before resuming your request.
It allows your code to say explicitly: "I'm waiting for a result that
will be available later", and so the framework to handle it as "Ok I
will stop your code, reuse the thread to serve other requests, and
resume your code as soon as the promised value you wait for is
available".

It is the point of the await(…) controller methods:

Promise<String> delayedResult = veryLongComputation(…);
await(delayedResult);

-- Continuations:

Because the framework needs to recover the thread you were using in
order to use it to serve other requests, it has to suspend your code.
In the previous Play version the await(…) equivalent was waitFor(…).
And waitFor was suspending your action, and then recalling it later
from the beginning.

To make it easier to deal with asynchronous code in Play 1.2 we have
introduced continuations. Continuations allow your code to be
suspended and resumed transparently. So you write your code in a very
imperative way, as:

public static void computeSomething() {
Promise<String> delayedResult = veryLongComputation(…);
String result = await(delayedResult);
render(result);
}

In fact here, your code will be executed in 2 steps, in 2 different
threads. But as you see it, it's very transparent for your application
code.

Using await(…) and continuations, you could write a loop:

public static void loopWithoutBlocking() {
for(int i=0; i<10; i++) {
System.out.println(i);
await("1s");
}
renderText("Loop finished");
}

And using only 1 thread (which is the default in development mode) to
process requests, Play 1.2 will be able to run concurrently these
loops for several requests at the same time.

-- Response streaming:

Now, because you are able to loop without blocking the request,
perhaps you want to send data to the browser as soon you have part of
the result available. It is the point of the "Content-Type:Chunked"
HTTP response type. It allows to send your HTTP response is several
times using multiples chunks. The browser will receive these chunk as
soon as they are published.

Using await(…) and continuations, you can now achieve that using:

public static void generateLargeCSV() {
CSVGenerator generator = new CSVGenerator();
response.contentType = "text/csv";
while(generator.hasMoreData()) {
String someCsvData = await(generator.nextDataChunk());
response.writeChunk(someCsvData);
}
}

Even if the CSV generation take 1 hour, Play 1.2 will be able to
process simultaneously several requests using a single thread, sending
back the generated data to the client as soon as they are available.

-- WebSockets:

WebSockets are a way to open a 2 way communication channel between a
browser and your application. On the browser side, you open a socket
using a "ws://" url:

new Socket("ws://localhost:9000/helloSocket?name=Guillaume")

On the Play side you declare a WS route:

WS /helloSocket MyWebSocket.hello

MyWebSocket is a WebSocketController. A WebSocket controller is like a
standard HTTP controller but handle different concepts:

- It has a request object, but no response object.
- It has access to the session but for read only.
- It doesn't have renderArgs, routeArgs, nor flash scope.
- It can read params only from the route pattern or from the QueryString.
- It has 2 communication channels: inbound and outbound.

When the client connects to the ws://localhost:9000/helloSocket
socket, Play will invoke the MyWebSocket.hello action method. Once the
MyWebSocket.hello action method exit, the socket is closed.

So a very basic socket example would be;

public class MyWebSocket extends WebSocketController {

public static void hello(String name) {
outbound.send("Hello %s!", name);
}

}

Here when the client connects to the socket, it receive the 'Hello
Guillaume' message, and then Play closes the socket.

Of course usually you don't want to close the socket immediately. But
it is easy to achieve using await(…) and continuations.

For example a basic Echo server:

public class MyWebSocket extends WebSocketController {

public static void echo() {
while(true) {
WebSocketEvent e = await(inbound.nextEvent());

if(e instanceof WebSocketFrame) {
WebSocketFrame frame = (WebSocketFrame)e;
if(!e.isBinary) {
outbound.send("Echo: %s", frame.textData);
}
}
}
}

}

-- Pattern Matching:

In the previous example, the imbricated 'if' and 'cast' soup was
tedious to write and error prone. And here Java sucks. Even for this
simple case it is not easy to handle. And for more complicated cases
where you combine several streams, and have even more event types, it
becomes a nightmare.

That's why we felt that we needed pattern matching in Java.
Unfortunately Java has not built-in pattern matching, and because of
the lack of function, it is difficult to add it as a library. Anyway
we've worked on a solution that is not so bad.

Our idea was to use the latest 'for loop' syntax to achieve basic
pattern matching for Java. Pattern matching must both check if your
object matches the required conditions and extract the interesting
value. The Pattern matching library for Play is part of the
play.libs.F library.

Let's see a first example: you have a reference of type Object and you
want to check that it is a string that starts by "command:". The
standard way would be:

Object o = anything();

if(o instanceof String && ((String)o).startsWith("command:")) {
String s = (String)o;
System.out.println(s.toUpperCase());
}

Using the Play pattern matching library, you can write it as:

for(String s: String.and(StartsWith("command:")).match(o)) {
System.out.println(s.toUpperCase());
}

The for loop is executed once, only if the condition is met, and it
automatically extracts the String value without the need of casting.
Because there is no explicit cast, all this thing is type safe, and
checked by the compiler.

We'll provide a good set of standard matchers, you can easily add
yours, and libraries like will WebSockets provide theirs.

So for example, we can rewrite our previous echo sample as:

public static void echo() {
while(true) {
WebSocketEvent e = await(inbound.nextEvent());

for(String msg: TextFrame.match(e)) {
outbound.send("Echo: %s", frame.textData);
}
}
}

A more complete example of WebSocket is available in the new Chat application:

https://github.com/playframework/play/blob/master/samples-and-tests/chat/app/controllers/WebSocket.java

--

I'm sure that all these new features will make of Play 1.2 the best
option to build complicated asynchronous Web applications in Java.
Thanks to all those that have contributed different parts of these new
features.

--
Guillaume Bort, http://guillaume.bort.fr

Daniel Guryca

unread,
Feb 11, 2011, 9:02:56 AM2/11/11
to play-fr...@googlegroups.com
Well guys this is huge :)

Greate job !
Daniel

> --
> You received this message because you are subscribed to the Google Groups "play-framework" group.
> To post to this group, send email to play-fr...@googlegroups.com.
> To unsubscribe from this group, send email to play-framewor...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/play-framework?hl=en.
>
>

Johan Vosloo

unread,
Feb 11, 2011, 9:26:18 AM2/11/11
to play-fr...@googlegroups.com
*Phew*... just when I thought my favourite framework couldn't get any better. 
Great job!

Artem Medeu

unread,
Feb 11, 2011, 9:45:52 AM2/11/11
to play-fr...@googlegroups.com
Wow! Just wow!

My favourite framework gets better with every commit!

Olivier Refalo

unread,
Feb 11, 2011, 10:15:42 AM2/11/11
to play-fr...@googlegroups.com
That's a Tsunami of new features... some will take time to assimilate and use in a proper way.

Cheers,

Ilkka Huotari

unread,
Feb 11, 2011, 11:46:03 AM2/11/11
to play-fr...@googlegroups.com
Can I ask if there is a support for the "simpler" version of websockets, which is Eventsource? Maybe it's possible to use Promises for that?

About the features themselves, they seem to look like Scala quite a bit. As someone who is using Play with Scala, I'm not really sure if that's a good thing for me. I'll wait for others' opinions though... 

Guillaume Bort

unread,
Feb 11, 2011, 12:08:25 PM2/11/11
to play-fr...@googlegroups.com
I don't know what is EventSource. Is there any specification for that?

> --
> You received this message because you are subscribed to the Google Groups
> "play-framework" group.
> To post to this group, send email to play-fr...@googlegroups.com.
> To unsubscribe from this group, send email to
> play-framewor...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/play-framework?hl=en.
>

--
Guillaume Bort, http://guillaume.bort.fr

For anything work-related, use g...@zenexity.fr; for everything else,
write guillau...@gmail.com

Dirk

unread,
Feb 11, 2011, 12:12:46 PM2/11/11
to play-fr...@googlegroups.com
Wow. Great work! This is pretty amazing stuff...

About the features themselves, they seem to look like Scala quite a bit. As someone who is using Play with Scala, I'm not really sure if that's a good thing for me. I'll wait for others' opinions though... 

I agree, it looks like a gradual scalafication of java :) I would like to see play/scala fleshed out into a feature-complete alternative to play/java. Intuitively, scala seems like a more natural means of expression of the concepts behind play than java does. On the other hand, while scala is still maturing as a language it's fantastic to have these additions to Java available.

Ilkka Huotari

unread,
Feb 11, 2011, 12:15:34 PM2/11/11
to play-fr...@googlegroups.com
I asked about it in here just recently (I think this went unnoticed). The other name is Server-Sent Events:  
https://groups.google.com/d/topic/play-framework/lFrJM3oOH60/discussion

Basically it's just a one-directional (from server to browser) as websockets is two directional. This might have bigger implications on the underlying requirements of course, I don't really know.

Guillaume Bort

unread,
Feb 11, 2011, 12:19:41 PM2/11/11
to play-fr...@googlegroups.com
Ok, but you can already do the same with WebSocket right?

Ilkka Huotari

unread,
Feb 11, 2011, 12:45:29 PM2/11/11
to play-fr...@googlegroups.com
Ok, but you can already do the same with WebSocket right?

(damn, I would like to use the plain text mode with the new google groups)

Yes, I could use WebSockets, but Server Sent Events are simpler in many ways. Actually, I'm not even sure they need extra support from the web server. Here's a post from Ian Hickson which explains some differences: http://www.mail-archive.com/public-...@w3.org/msg08196.html

Yes, he says that they work with existing servers. Maybe I should find out how... 

 

Guillaume Bort

unread,
Feb 11, 2011, 1:29:21 PM2/11/11
to play-fr...@googlegroups.com
Perhaps it can be useful for servers that can't support WebSocket, but
since Play now supports WebSocket I don't see your point? The problem
is more related to browsers, that doesn't support WebSocket yet. And I
guess that they doesn't support EventSource neither... ?

Ilkka Huotari

unread,
Feb 11, 2011, 1:46:19 PM2/11/11
to play-fr...@googlegroups.com
Well, maybe I was too quick to ask it here, and in the wrong place (wrong thread). But I'll get back to it later. 

Julien Richard-Foy

unread,
Feb 11, 2011, 2:48:01 PM2/11/11
to play-fr...@googlegroups.com
Really interesting post.

Isn’t there an error on the pattern matching example? Wouldn’t it be that?

for(String s: ClassOf(String.class).and(StartsWith("command:")).match(o)) {
System.out.println(s.toUpperCase());
}

And, as others said, I wonder why you do not completely shift to Scala
instead of trying to bypass Java limitations… There are so many things
in Play! that just bypass Java limitations: public attributes on
models (easy to write as variables declarations with scala), groovy as
an expression language in the templates (since Java does not provide
Options nor a convenient collection API), and now the functionnal
library. All that is very very interesting since it gives Java
programmers more expressivity and power, but why don’t you just focus
on Scala?

Guillaume Bort

unread,
Feb 11, 2011, 3:13:31 PM2/11/11
to play-fr...@googlegroups.com
Well I've a String matcher locally that I have not yet committed but that is the equivalent of ClassOf(String.class).

About scala, from my point of view it is still too early to switch completely to it. I think that scala has the potential to become the new java in the next years but for not yet.

Ike

unread,
Feb 11, 2011, 3:31:51 PM2/11/11
to play-fr...@googlegroups.com
I don't think it's too early to switch to Scala for specific projects but in terms of overall market support, skills availability, tools, etc. I agree that there's still a long way to go.

However, I don't see a technical reason not to support these features in an idiomatic Scala way with the Scala module, other than the obvious work involved.

grandfatha

unread,
Feb 11, 2011, 3:40:05 PM2/11/11
to play-framework
This is insane. I cant believe I have all those power in my hands now
thanks to you guys. Play is the future of Java web development for
sure.

One stupid question, though: Will that while(true)-loop ever exit? Or
only when the Play app is stopped?

Sadek Drobi

unread,
Feb 11, 2011, 4:32:40 PM2/11/11
to play-fr...@googlegroups.com
The main vision is to have (Scala and Java) Play evolving together, but every feature will be implemented as native to the language as possible. Keeping of course certain similarities for learning curve.

Having features implemented natively allows you to use your language skills. And about the Java vs Scala question: There are a lot of people out there using Java, and there are some other people using/willing_to_use Scala. Users of Java will continue being comfortable using the language (Most of the "Functional" stuff in the new libraries is for plumbing and one don't need to fully grasp it). Users of Scala will have powerful interfaces to fully use the power and potential of the language.

Of course, and quite obvious through the announcement of the new libs, this is without sacrificing the dynamism of the framework.

Sadek

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To post to this group, send email to play-fr...@googlegroups.com.
To unsubscribe from this group, send email to play-framewor...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/play-framework?hl=en.




--
www.sadekdrobi.com
ʎdoɹʇuǝ

Ilkka Huotari

unread,
Feb 11, 2011, 5:33:36 PM2/11/11
to play-fr...@googlegroups.com
I don't want to be a pain, but I tested a bit with Apachebench and I noticed a few millisecond (1-3 ms) longer response times from the current 1.2 version vs. 1.1.1 (installed from the zip file). The tested apps were quite simple. Just FYI. I understand that 1.2 isn't ready yet...

Of course I'm happy with all the activity with Play development (and I thank you for that), so the point is not to complain, just give some feedback, which I hope isn't totally worthless. 

Guillaume Bort

unread,
Feb 11, 2011, 6:18:17 PM2/11/11
to play-fr...@googlegroups.com
There are no reasons that 1.2 would ne slower than 1.1. We are still using the same server and the code doesn't impact classical requests. 


On 11 févr. 2011, at 23:33, Ilkka Huotari <ilk...@gmail.com> wrote:

I don't want to be a pain, but I tested a bit with Apachebench and I noticed a few millisecond (1-3 ms) longer response times from the current 1.2 version vs. 1.1.1 (installed from the zip file). The tested apps were quite simple. Just FYI. I understand that 1.2 isn't ready yet...

Of course I'm happy with all the activity with Play development (and I thank you for that), so the point is not to complain, just give some feedback, which I hope isn't totally worthless. 

--

Guillaume Bort

unread,
Feb 11, 2011, 6:19:44 PM2/11/11
to play-fr...@googlegroups.com
It depends of the loop but anyway the continuations will not be invoked again if the corresponding HTTP request is closef on the browser side. So the loop will stop.

v6ak

unread,
Apr 6, 2011, 4:30:14 AM4/6/11
to play-framework
That looks great. But I've a little question about WebSockets support.
Since there are browsers that don't support it, it is good idea to
implement an alternative. (Well, Play! can probably implement some of
these alternatives, but it is not the point of this post. I'm about to
do it myself and maybe provide other ways for premium uses only, since
there is more overhead.)

So, I'd implement it myself and it would be great to be able to
implement it in the same Controller. There can be two ways:
* implement both of them in the WebSocketController (IMHO unclean)
* implement both of them in ordinar Controller (unsure if it works)
What is the best way?

Regards
Vít Šesták 'v6ak'
> https://github.com/playframework/play/blob/master/samples-and-tests/c...

Guillaume Bort

unread,
Apr 6, 2011, 5:15:22 AM4/6/11
to play-fr...@googlegroups.com
You can't use WebSocket controller to handle classic HTTP request as
they have a different semantic. In particular, WebSocketController do
not give access to the HTTP response.

On Wed, Apr 6, 2011 at 10:30 AM, v6ak <v6...@volny.cz> wrote:
> That looks great. But I've a little question about WebSockets support.
> Since there are browsers that don't support it, it is good idea to
> implement an alternative. (Well, Play! can probably implement some of
> these alternatives, but it is not the point of this post. I'm about to
> do it myself and maybe provide other ways for premium uses only, since
> there is more overhead.)
>
> So, I'd implement it myself and it would be great to be able to
> implement it in the same Controller. There can be two ways:
> * implement both of them in the WebSocketController (IMHO unclean)
> * implement both of them in ordinar Controller (unsure if it works)
> What is the best way?
>
> Regards
> Vít Šesták 'v6ak'
>
> On Feb 11, 3:25 pm, Guillaume Bort <guillaume.b...@gmail.com> wrote:
>> Hi all,
>>
>> The whole refactoring for better asynchronism management in Play 1.2,
>> is almost finished and available in the Play git master.
>>
>> These new features cover several points I will introduce here:
>>
>> - Promises
>> - A new Functional style library (play.libs.F)

>> - await(...)


>> - Continuations
>> - Response streaming
>> - WebSockets
>> - Pattern matching
>>
>> First, it is already possible to achieve asynchronism with Play 1.1
>> using Java Future and waitFor(...) and suspend(...) controller
>> methods. However these primitives was not really easy to use. That's
>> why we've worked on a complete set of new coherent features for Play
>> 1.2.
>>
>> -- Promises:
>>
>> In Play 1.2 we introduce Promise that is the Play's custom Future type
>> (Promise was named Task in previous commits on master) . In fact a
>> Promise<T> is also a Future<T> so you can use it as a standard Future.
>> But it has also a very interesting property: the ability to register

>> callback using onRedeem(...) that will be called as soon as the promised


>> value is available. It allows the framework to register itself on them
>> and to reschedule the request invocation as soon as possible.
>>
>> Promises are used everywhere in Play in place of Future (for Jobs,

>> WS.async, etc...)


>>
>> Promises can be combined in several way. For example:
>>
>> - Promise p = Promise.waitAll(p1, p2, p3)
>> - Promise p = Promise.waitAny(p1, p2, p3)
>> - Promise p = Promise.waitEither(p1, p2, p3)
>>
>> -- play.libs.F:
>>
>> The Promise type is part of new library (play.libs.F) that introduces
>> several useful constructs coming from functional programming. These
>> constructs are used to handle complex cases that I will expose just
>> later. For those that are accustomed to functional programming we
>> provide:
>>
>> - Option<T> (a T value that can be or not set)
>> - Either<A,B> (contains either a A value or a B value)
>> - Tuple<A,B> (contains both A and B values)
>>

>> -- await(...):


>>
>> So, now when your application code returns values that are not yet
>> available using a Promise<T>, you want to be able to ask Play to wait
>> for this promised result to be available before resuming your request.
>> It allows your code to say explicitly: "I'm waiting for a result that
>> will be available later", and so the framework to handle it as "Ok I
>> will stop your code, reuse the thread to serve other requests, and
>> resume your code as soon as the promised value you wait for is
>> available".
>>

>> It is the point of the await(...) controller methods:
>>
>> Promise<String> delayedResult = veryLongComputation(...);


>> await(delayedResult);
>>
>> -- Continuations:
>>
>> Because the framework needs to recover the thread you were using in
>> order to use it to serve other requests, it has to suspend your code.

>> In the previous Play version the await(...) equivalent was waitFor(...).


>> And waitFor was suspending your action, and then recalling it later
>> from the beginning.
>>
>> To make it easier to deal with asynchronous code in Play 1.2 we have
>> introduced continuations. Continuations allow your code to be
>> suspended and resumed transparently. So you write your code in a very
>> imperative way, as:
>>
>> public static void computeSomething() {

>>      Promise<String> delayedResult = veryLongComputation(...);


>>      String result = await(delayedResult);
>>      render(result);
>>
>> }
>>
>> In fact here, your code will be executed in 2 steps, in 2 different
>> threads. But as you see it, it's very transparent for your application
>> code.
>>

>> Using await(...) and continuations, you could write a loop:


>>
>> public static void loopWithoutBlocking() {
>>      for(int i=0; i<10; i++) {
>>           System.out.println(i);
>>           await("1s");
>>      }
>>      renderText("Loop finished");
>>
>> }
>>
>> And using only 1 thread (which is the default in development mode) to
>> process requests, Play 1.2 will be able to run concurrently these
>> loops for several requests at the same time.
>>
>> -- Response streaming:
>>
>> Now, because you are able to loop without blocking the request,
>> perhaps you want to send data to the browser as soon you have part of
>> the result available. It is the point of the "Content-Type:Chunked"
>> HTTP response type. It allows to send your HTTP response is several
>> times using multiples chunks. The browser will receive these chunk as
>> soon as they are published.
>>

>> Using await(...) and continuations, you can now achieve that using:

>> it is easy to achieve using await(...) and continuations.

> --
> You received this message because you are subscribed to the Google Groups "play-framework" group.
> To post to this group, send email to play-fr...@googlegroups.com.
> To unsubscribe from this group, send email to play-framewor...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/play-framework?hl=en.
>
>

--
Guillaume Bort, http://guillaume.bort.fr

For anything work-related, use g...@zenexity.fr; for everything else,
write guillau...@gmail.com

v6ak

unread,
Apr 6, 2011, 9:21:07 AM4/6/11
to play-framework
Hmm, I see that WebSocketController is NOT a Controller. So, that is
the point.

However, the sitution seems to be painful:
* I probably can't write anything similar to
https://github.com/playframework/play/blob/master/samples-and-tests/chat/app/controllers/WebSocket.java
, but I can't figure the reason out. Well, I've tried it for ordinar
Controllers only.
* I can't use traits with controllers because of a bug. (It seems to
be a Javassist's bug, that probably does not accept more fields with
the same name and different type. Note that it is legal in Java
bytecode.)

Additionaly, I can't compile following with RC2: https://gist.github.com/905622

Do I have to use Java for WS?

On Apr 6, 11:15 am, Guillaume Bort <guillaume.b...@gmail.com> wrote:
> You can't use WebSocket controller to handle classic HTTP request as
> they have a different semantic. In particular, WebSocketController do
> not give access to the HTTP response.
>
> On Wed, Apr 6, 2011 at 10:30 AM, v6ak <v...@volny.cz> wrote:
> > That looks great. But I've a little question about WebSockets support.
> > Since there are browsers that don't support it, it is good idea to
> > implement an alternative. (Well, Play! can probably implement some of
> > these alternatives, but it is not the point of this post. I'm about to
> > do it myself and maybe provide other ways for premium uses only, since
> > there is more overhead.)
>
> > So, I'd implement it myself and it would be great to be able to
> > implement it in the same Controller. There can be two ways:
> > * implement both of them in the WebSocketController (IMHO unclean)
> > * implement both of them in ordinar Controller (unsure if it works)
> > What is the best way?
>
> > Regards
> > Vít ¦esták 'v6ak'
> ...
>
> read more »

Guillaume Bort

unread,
Apr 7, 2011, 3:57:28 AM4/7/11
to play-fr...@googlegroups.com
Yes for now it's not yet available for Scala.

sas

unread,
Apr 7, 2011, 11:44:58 PM4/7/11
to play-framework
about the scala/java discussion, I think the devs are making the right
choice, they develop a great java web framework that also provides a
smooth way to scala... no other framework even think about providing
such a thing...



On 7 abr, 04:57, Guillaume Bort <guillaume.b...@gmail.com> wrote:
> Yes for now it's not yet available for Scala.
>
>
>
>
>
>
>
> On Wed, Apr 6, 2011 at 3:21 PM, v6ak <v...@volny.cz> wrote:
> > Hmm, I see that WebSocketController is NOT a Controller. So, that is
> > the point.
>
> > However, the sitution seems to be painful:
> > * I probably can't write anything similar to
> >https://github.com/playframework/play/blob/master/samples-and-tests/c...
> >> >> becomes a...
>
> leer más »

Tony Xiao

unread,
Apr 15, 2011, 8:32:44 AM4/15/11
to play-fr...@googlegroups.com
Are there any additional references on how to use the libs.F matcher library in addition to those ones provided in the chat application example/


Guillaume Bort

unread,
Apr 19, 2011, 1:45:44 PM4/19/11
to play-fr...@googlegroups.com
No but please ask if you search something special.

On Fri, Apr 15, 2011 at 2:32 PM, Tony Xiao <tony...@gmail.com> wrote:
> Are there any additional references on how to use the libs.F matcher library
> in addition to those ones provided in the chat application example/
>

Reply all
Reply to author
Forward
0 new messages