views:

167

answers:

7

I have a simple ajax game between 2 users with java backend (tomcat, spring). I need some good way of notifying one user that his opponent made a turn. Now all communication is done through database and waiting for opponent to finish his turn looks like this:

while(!timeout && !opponentIsDone) {
     //...get the game record from db and check if opponent made turn
     Thread.sleep(100);
}

Can I somehow get rid of this loop with sleep() and get instantly notified without a delay (but with timeout)? I can probably make some global static var and communicate through it, but I still will need similar loop only maybe timeout will be smaller.

I can't just call some method once the turn is done because it is all need to go to the browser through ajax and I can't push data there, only pull. So I need to have process that waits for the opponent.

I am looking for some light and simple solution.

Thanks.

+2  A: 

You may want to look into Tomcat's advanced IO (Comet) support.
http://tomcat.apache.org/tomcat-6.0-doc/aio.html

Jataro
Thanks, I read about it but it seems like overkill... I would prefer something as simple as possible.
serg
Before Tomcat 6 I rolled my own notification system. It was by no means simple though. Its a tough problem because of the stateless nature of http.
Jataro
+2  A: 

I think you're looking for the Distributed Events (aka Subscriber/Publisher) pattern, and I believe Dojo Framework has implemented it: http://ajaxpatterns.org/Distributed_Events

gravyface
If I understood correctly that article it is still uses a loop similar to mine only instead of checking for database record it is checking for events. I might do the same just with a static variable.
serg
Cool. Would appreciate an answer on this question if you're satisfied.
gravyface
+1  A: 

There are many ways to push notifications to a web client. Gmail's IM client is an excellent example of this sort of thing. This is often accomplished by holding an open HTTP connection in some manner, and this family of techniques is referred to as COMET. Wikipedia has an article on it, and there are blogs dedicated to the subject ( http://cometdaily.com/ ).

Even if you didn't use this technique, there are still many improvements you can make to the algorithm you identified in your question. One way would be to use a wait/notify sort of pattern or a subscriber/publisher approach. Another would be to return a "waiting for other player to make a turn" page immediately, and have that page automatically refresh every few seconds until the other player has taken his turn.

I think the solution you're looking for is COMET-style notification, though.

CaptainAwesomePants
Well, I am already holding an open http connection while waiting for an opponent so I am already using a comet approach (in wiki they call it Ajax with long polling). My only concern is that I want to get rid of sleep and get immediate notification. All those approaches in your second paragraph are using basically the same waiting in the loop technique I already have.
serg
+1  A: 

If you had a global static var of some sort, you could use a java.util.concurrent.BlockingQueue<T>

BlockingQueue<Turn> handoff = new ArrayBlockingQueue<Turn>(1);

// opponent thread
handoff.offer(myTurn);

// other thread can use
Turn otherTurn = handoff.poll( 90, TimeUnit.SECONDS );

if ( otherTurn == null )
// then no turn made

You can easily make the people wait for each other by using SynchronousQueue instead of ArrayBlockingQueue.

and of course it doesn't need to be global static -- it could be anything accessible to both users.

Darren Gilroy
+1  A: 

flex/flash has a real-time chatroom system (using remote-object programming).

you have to install BlazeDS (free) http://opensource.adobe.com/blazeds/, it comes with sample application. This is called AMF technology. I think Spring does support this AMF in one way or another.

http://www.adobe.com/devnet/livecycle/articles/blazeds_spring.html http://blog.springsource.com/2008/12/17/using-spring-blazeds-integration-m1/

It's good for Flash based website. However, if you don't want to use flash, i think u can hide it or make it small enough, just to use it as a communication channel on your page.

Perhaps you have to find a way to notify your webpage/javascript after flash receive data from server.

Yeah, I know this method is a bit hacky, and it's not a clean way of doing thing :) just to provide an alternative for you.

janetsmith
+1  A: 

DWR (Direct Web Remoting) is a package that allows you to make Java methods on the server directly available to Javascript (by creating a proxy). It has a feature called "Reverse Ajax" that is an easy way to handle push scenarios.

JacobM
A: 

Perhaps consider Jetty Continuations if you aren't locked into Tomcat?

http://bill.burkecentral.com/2008/11/12/buggybroken-tomcat-6-comet-nio-apis/ has some discussion about Tomcat NIO

anger