Chat in the Cloud with MongoHQ
Going back in time, I published a blog post about a new eXo Add-On: eXo Community Chat.
You can read more about it here: eXo Platform Add-ons: Chat in Space
As I promised some technical posts about the technology I used, I wrote a first post about MongoDB: Chat Application: Why MongoDB?
Now, it’s time to see all the coolness of MongoDB inside an eXo app. We will see in this post how easy it is to switch to a Cloud storage using MongoHQ service and what are the impacts for your app.
Documents Storage in the Cloud
We all know – developers – that running a same web app locally and on a production server is not the same in terms of response time. Locally, you have everything on the same machine. When you’re in Production, you have different setups, network lags, etc.
But more than that, we’re now living in a must-be-Cloud-ready world. You develop in the Cloud – Cloud IDE – share your work in the Cloud – GitHub – deploy in the Cloud – CloudBees and Co – run in the Cloud – Cloud Workspaces – and store every single piece of it In The Cloud – MongoHQ. Isn’t it clear enough? 🙂
So, I decided to give MongoHQ a try and see what the user experience would be if development was done this way in production.
Lag: Manage it the right way
I don’t blame the internet for being slow or MongoHQ for giving me a shared/slow machine for my free subscription. When I choose to take a free service, I choose to pay the price for this… and it means: no dedicated server!
I think it even has a great side: you must think about your app differently as it will lag from time to time. So, you must respect that so the end-user experience doesn’t suffer.
MongoHQ comes with a great user interface (another one using responsive design – I love that).
If you work with MongoDB, you certainly know about MongoHQ but if you don’t, give it a try, it’s damn easy to set up. So, not that much to do on my side. I wrote a PropertyManager so I can get properties stored in the tomcat/conf. So, I just switched from:
dbServerHost=localhost dbServerPort=27017 dbName=chat dbAuthentication=false
To this:
dbServerHost=alex.mongohq.com dbServerPort=10005 dbName=chat dbAuthentication=true dbUser=admin dbPassword=dontimagineiwillgiveyoumypassword
It’s all mentioned on MongoHQ when you create your database.
Once it’s done, you’re ready to go, just reload the server and you’re now connected to a database in the Cloud. It’s that easy!
Elegant, isn’t it?
On the Java side, it looks like this:
String host = PropertyManager.getProperty(PropertyManager.PROPERTY_SERVER_HOST); int port = Integer.parseInt(PropertyManager.getProperty(PropertyManager.PROPERTY_SERVER_PORT)); m = new Mongo(new ServerAddress(host, port), options); m.setWriteConcern(WriteConcern.SAFE); ... boolean authenticate = "true".equals(PropertyManager.getProperty(PropertyManager.PROPERTY_DB_AUTHENTICATION)); if (authenticate) { db.authenticate(PropertyManager.getProperty(PropertyManager.PROPERTY_DB_USER), PropertyManager.getProperty(PropertyManager.PROPERTY_DB_PASSWORD).toCharArray()); }
JavaScript is great too
On the client side, I also ask myself a few questions. The easy answer for a Java developer is often when he designs an app is to use one way to develop and stick with it. I’ve seen that a lot.
So, you decide to write a JSF/Hibernate application. Each time you have a human interaction you use JSF Controllers.
With libraries – frameworks – like JQuery, you can actually do a lot on the client side. The bonus is, everything done on the browser doesn’t need to be on the server.
A server call is not needed when it’s not needed
I will give two examples: I get the room data as a simple JSon feed with a jQuery Ajax call:
{"room": "50bf230ac51064038e31cedf","timestamp": "1354711914497","messages": [{"user": "john","fullname": "John Smith","date": "05/12/2012 11:44 AM","message": "alors "},{"user": "john","fullname": "John Smith","date": "05/12/2012 11:44 AM","message": "How are you? "},{"user": "mary","fullname": "Mary Williams","date": "05/12/2012 11:45 AM","message": "I'm great "},{"user": "john","fullname": "John Smith","date": "05/12/2012 11:57 AM","message": "cool "},{"user": "james","fullname": "James Davis","date": "05/12/2012 01:51 PM","message": "Hi guys "},{"user": "john","fullname": "John Smith","date": "05/12/2012 01:51 PM","message": "Hi James "},{"user": "mary","fullname": "Mary Williams","date": "05/12/2012 01:51 PM","message": "Hi James "},{"user": "mary","fullname": "Mary Williams","date": "05/12/2012 01:51 PM","message": "How are you ? "},{"user": "james","fullname": "James Davis","date": "05/12/2012 01:51 PM","message": "I'm fine "},{"user": "james","fullname": "James Davis","date": "05/12/2012 01:51 PM","message": "thanks "}]}
In terms of server calls, it’s the most efficient way of doing it I think.
Then, all the formatting, decoration, beautifiers is done with JS code, to get something like this:
Another example of the search. For now, I will stick with a local JS search.
As JSon messages are stored locally, the search uses them and is then decorated and redrawn using jQuery.
One question we always have to ask ourselves now is: Do I really need a server call to do this?
In this search scenario, I originally did a server-side search. But, it wasn’t as fast as I wanted it to be. So, the downside for now is I don’t search on all rooms. In the future, if I want to do cross room searches, I will either update and store locally using HTML5 storage (my 2 cents on this) or I will do a server call. This still has to be tested to choose the best solution.
In the end, if you take a look at my code, you will see a lot of jQuery in it (but not that much).
Asynchronous is the key
On the client side, as MongoHQ is not as fast as a local server, I asked myself also how I could send feedback without being affected by possible lag.
Thus, when you log in, you have a Waiting Connection panel until everything is displayed (like on Skype by the way).
For a regular web page, it wouldn’t be that important but we’re talking about a near-to-real-time application here, thus, we must give some feedback to create a better user experience.
Another example is when I post a message. I first add it to the current JSon tree and display it. Then, I use an async Ajax call to send the data and get it back to update the chat window with all updates.
What’s next?
Next year :), I will write a final post on the Chat application about Juzu and how you can easily write both a Java Portlet and a standalone application with this great web framework.
If you read these posts to the end, I first give you a big thank for your reading time.
You want to know more or help me to build an even better Chat application? Contact me or simply fork the Chat GitHub project, I’ll be more than happy to integrate new cool ideas in the Chat (or bug fixes).
Thus, if you want to take a deeper look at the code, it’s Open Source and available on eXo Addons Repositories: https://github.com/exo-addons/chat-application
« Again, thanks for reading and stay tuned – more things are coming, Benjamin. »