Preparing for the Mobile World

So we have a web interface for our Virtual Queues. That’s a good start, but to make the queues really useful, they need to be available from anywhere. With the flooding of smart phone and tablets in the market, we need to open our queues up for use from these devices. If you are in a grocery store, chances are that you have your smart phone with you, Using the mobile app, one can locate a queue for the deli section or a queue for the pharmacy and can get on the queue using their mobile device.

In order to achieve this, we will have to open our application for the mobile platform. The main challenge is the same as for the web interface; we need an ability to update all the devices and web interfaces that are on the same queue as soon as the state of the queue changes. We still do not have the Queues coded yet but we will add them soon, however, we have the beginnings of a queue – our TokenDispenser. On the web front we were able to achieve this capability of real time client updates using long-polling mechanism and Comet support in Lift. Things are not so simple when it comes to mobile devices. In today’s blog we will discuss the modifications we need to make in preparation of the mobile platform.

Opening another channel to our server – using Sockets

To support instant client updates for the mobile devices, we will open a socket on the server. The server will use this socket for sending updates to all the clients registered and listening on the socket. As part of the boot process we will open a Socket to listen on  a port. As soon as a connection is established on that socket, we will immediately spawn out a new thread (Actor) to handle the client. Here is the code for opening and listening on a socket.

[sourcecode language=”scala”]
private val socketServer = actor {
val port = Props.getInt("socketBasedTokenObserver.port", 7777)
try {
val listener = new ServerSocket(port)
while (true) SocketBasedTokenObserver(listener.accept())
listener.close()
}
catch {
case e: IOException => System.err.println("Could not connect to port: " + port)
}
}
[/sourcecode]

This code is part of the Boot class. Notice how we have made socketServer an actor. As soon as the system boots up the actor starts in its own thread. It gets the port number for opening a socket from default.props file under the resources directory. This actor will then create a new ServerSocket and will wait on the socket to see if anyone attempts to connect. When a client connects to this socket, the server will spawn a new actor “SocketBasedTokenObserver”, it will hand the newly created Socket connection to this observer and will get back to waiting for more connections. The SocketBasedTokenObserver is itself an Actor and so it will run in its own thread. Here is the code for SocketBasedTokenObserver –

[sourcecode language=”scala”]
package Lift.comet

import net.liftweb.actor.LiftActor
import java.net.{SocketException, Socket}
import java.io.DataOutputStream
import net.liftweb.http.{RemoveAListener, AddAListener}

/**
*
* User: Anupam Chandra
*/
case class SocketBasedTokenObserver (socket: Socket) extends LiftActor{
TokenRefresher ! AddAListener(this)
val out = new DataOutputStream(socket.getOutputStream())

def messageHandler = {
case x: Int => {
out.writeInt(x)
}
}

override def exceptionHandler = {
case e: SocketException => TokenRefresher ! RemoveAListener(this)
case _ => {
if (socket.isConnected){
if (!socket.isOutputShutdown) out.close()
socket.close()
}
TokenRefresher ! RemoveAListener(this)
super.exceptionHandler
}
}
}
[/sourcecode]

The SocketBasedTokenObserver is a Lift Actor. Since it’s a LiftActor, we can directly register it with our TokenRefresher, the singleton ListenerManager that we discussed in the previous blog entry. The TokenRefresher not only register the Comet observers that update web sites but now it also registers the Socket based listeners that can update the mobile devices listening on a socket. It registers with the TokenRefresher by sending it a message of type AddAListener. Inside the AddAListener message is a self reference.

When the TokenRefreshes updates all its listeners, the messageHandler method provided by this class will be invoked. This method will then write the next token number out on to the DataOutputStream attached to the socket. That is how the mobile devices listening on the Socket will be updated.

Conclusion

Adding a Socket is the first step towards putting up a mobile interface. In my next blog entry I will discuss the next change we need to make to enable mobile devices – exposing a web service that the device could use to order the system to dispense it a token.

Leave a Reply

Your email address will not be published. Required fields are marked *