26. September 2010

A Website Chat made easy with XMPP and BOSH


A description of the live chat feature on http://avatar.lupuslabs.de/contact.html

10 years ago we spent weeks to develop a website chat. We implemented a chat server in C++, a PHP library, which talked to the chat server and JavaScript streaming in an iframe. Today it is much simpler.

Today we can use XMPP and BOSH and let the web page talk to my GTalk client, which runs all the time anyway.

Here is the shopping list of technologies:
These components do all the work. There is only some Javascript code and a little bit of plumbing required.

1. Set up ejabberd:

Download ejabberd from http://www.ejabberd.im/. The easiest way is to use the installer from http://www.process-one.net/en/ejabberd/downloads

For XMPP to work we need XMPP users. I prefer to run ejabberd with MySQL storage, because MySQL is the easiest way for me to add users and to manage the user list programatically. But the mnesia database also works.

Here is the config to use MySQL with ejabberd (to be added to ejabberd.cfg):
% {auth_method, internal}. % disabled
{auth_method, odbc}. % enabled
{odbc_server, {mysql, "localhost", "ejabberd", "mysql-user", "mysql-password"}}
Also I comment out XMPP in-band account registration, so that nobody creates users on my server:
{access, register, [{deny, all}]}.
This article explains how to create tables for ejabberd in the MySQL server: https://support.process-one.net/doc/display/MESSENGER/Using+ejabberd+with+MySQL+native+driver

2. Set up Apache as BOSH proxy:

Enable Apache modules "proxy" and "proxy_http". The debian way:
% a2enmod proxy
% a2enmod proxy_http
Add to the proxy configuration (Debian: proxy.conf)
ProxyPass /xmpp-httpbind http://127.0.0.1:5280/http-bind
ProxyPassReverse /xmpp-httpbind http://127.0.0.1:5280/http-bind
By default accessing the proxy is only allowed for localhost. Since Browers will access it, it needs to be accessible from anywhere. Add to the proxy configuration (Debian: proxy.conf)
Allow from all
ProxyRequests Off
3. Create an HTML file and start programming

Download Strophe and jQuery (or use the CDN version http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js). Add references to the HTML-head:
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
<script type="text/javascript" src='strophe.min.js'></script>
4. Now comes the real fun: coding

We basically create a BOSH connection from Javascript to ejabberd through apache/mod_proxy:
var conn = new Strophe.Connection('/xmpp-httpbind');
Create an XMPP user in MySQL (I am using phpmyadmin) and connect with this user:
conn.connect('test@wolfspelz.de', 'secret', OnConnectionStatus);
The OnConnectionStatus function may look like:

function OnConnectionStatus(nStatus)
{
if (nStatus == Strophe.Status.CONNECTING) {
} else if (nStatus == Strophe.Status.CONNFAIL) {
} else if (nStatus == Strophe.Status.DISCONNECTING) {
} else if (nStatus == Strophe.Status.DISCONNECTED) {
} else if (nStatus == Strophe.Status.CONNECTED) {
OnConnected();
}
}
When the connection is established, register message handlers and send our own presence:
function OnConnected()
{
conn.addHandler(OnPresenceStanza, null, "presence");
conn.addHandler(OnMessageStanza, null, "message");
conn.send($pres());
}
BTW: handlers should always return "true". Otherwise they are removed from the handler list. A message handler may look like:
function OnMessageStanza(stanza)
{
var sFrom = $(stanza).attr('from');
var sType = $(stanza).attr('type');
var sBareJid = Strophe.getBareJidFromJid(sFrom);
var sBody = $(stanza).find('body').text();
// do something, e.g. show sBody with jQuery
return true;
}
A presence handler may be:
function OnPresenceStanza(stanza)
{
var sFrom = $(stanza).attr('from');
var sBareJid = Strophe.getBareJidFromJid(sFrom);
var sType = $(stanza).attr('type');
var sShow = $(stanza).find('show').text();
// do something, e.g. show status icon with jQuery
return true;
}
The connection should be closed when the page unloads. Unfortunately strophe.js (at least up to version 1.0.2) disconnects asynchronously, which does not work when the page is destroyed. After some time the XMPP server will notice, that the page disappeared and will close the connection. But if you do not want to wait, then we have to force strophe to close immediately.

There is a patch, which allows for synchronous connection closing. The patch must be applied to the strophe.js file:
diff --git a/src/core.js b/src/core.js
index 5aeb06a..f79ae29 100644
--- a/src/core.js
+++ b/src/core.js
@@ -2161,7 +2161,8 @@ Strophe.Connection.prototype = {

             req.date = new Date();
             try {
-                req.xhr.open("POST", this.service, true);
+               var async = !('sync' in this && this.sync === true);
+                req.xhr.open("POST", this.service, async);
             } catch (e2) {
                 Strophe.error("XHR open failed.");
                 if (!this.connected) {
How to use the patch:
    this.conn.flush();
    this.conn.sync = true; // Set sync flag before calling disconnect()
    this.conn.disconnect();

5. Summary

Of course, all these functions and callbacks should be prototype based and bind the instance to the closure. We should also use a model-view architecture and handle the protocol stuff in the model, while notifying the view of really important events.

Here are the files:
contact.html - the "driver" which loads everything and produces the GUI
model.js - the model does it, classes: Model, Room, Participant
view.js - the view shows it, the view registers listeners with the model
utils.js - utility classes, logging, unit test, oberver pattern
config.js - configurations for test and production
setup.js - selects the appropriate configuration
style.css
lib/strophe.js - including the above patch
lib/jquery-1.4.2.min.js
lib/jquery-ui-1.8.5.custom.min.js
_happy_chatting()

11. September 2010

Service URLs should be Immutable

Service URLs are URLs where you (the client) expect a service. No surprise. Examples:

  • the URL of a SOAP WSDL is a service URL,
  • the REST URL of the Twitter timeline API: http://twitter.com/statuses/friends_timeline.xml,
  • name or URL of AJAX scripts of a web site,
  • a chat room URL provides a software bus service.
These service URLs are provided to the client. Usually they are configured. The client gets them somehow. The client uses them to access the service. BUT the client should never construct them or append to them or change them. Service URLs should be final.

Why? I don't know, but I feel, that it is a bad thing. I had several cases in real applications where constructing, appending to, manipulating service URLs made an application less extensible, more complex, less testable.

Extensibility: if the client constructs the service URL from parts, then future server changes must take the client URL construction into account. The server can not just supply a different service URL, because the client also does something and might prevent the server from changing the service URL stucture or the URL altogether. For example, if the client appends the path of a URL to a host name and if the client assumes, that the server language is PHP, then the service URL might always look like a PHP script, even if the server technology changes. Imagine the unfortunate sysadmin who has to configure a Java application server to serve ".php" URLs. The client will have to be changed when the server changes. This is bad.

Complexity: Constructing URLs in the client is more processing than doing nothing. It introduces IFs, methods, more constants. This is usually not a big issue, but it rare cases the additional complexity can be quite significant. I have seen these cases.

Testability: Service URLs point to resources. Resources are dependencies. A very important concept of unit testing is inversion of control by dependency injection. But if the client generates its dependencies, then inversion of control is more difficult, if not impossible. It is much better to let the server be in control by configuring the client for production and test cases.

Do not...
  • combine host name and path to URLs
  • append or decide on filename extensions
  • append query parameters
  • decide the protocol
  • insert or remove port numbers
...in the client. Just leave it as you get it. The server knows what's good for you.

Exceptions: however, you may...
  • decide the protocol (http vs. https) in AJAX clients for JS security reasons,
  • replace query arguments by treating the service URL as a template,
  • append URL parameters if (and only if) the service protocol consists of URL parameters (thanks Allan)
  • (any other exceptions?)
happy_webservicing()

16. August 2010

Stellenausschreibung Softwareentwickler/in

In den nächsten 12 Monaten bauen wir eine interne Entwicklung mit 2 Scrum Teams auf. Wir suchen besondere, gute Leute, die mit anpacken, Produkte und Projekte umsetzen und mit dem Unternehmen wachsen wollen. Wir haben hier die Chance eine moderne IT aufzubauen, moderner, als unser Top-Management für möglich hält. Alles ist neu, keine Altlasten. Neuer guter Code und Softwarearchitektur. Wer mich kennt, weiss, dass wir aktuelle Technologien verwenden: Agile, Scrum, Unittesting, Clean Code, SOLID, DRY,KISS und wir werden bald wieder ein regelmäßiges Developer-Seminar machen.

Ihre Aufgaben:
  • Selbständige Projektarbeit in einem Scrum- Team
  • Objektorientierte Analyse und Entwurf
  • Entwicklung von webbasierten Anwendungen und Webservices
  • Aktive Teilnahme an modernen agilen Entwicklungsprozessen
Ihre Skills:
  • Erfahrungen im Bereich objektorientierter Entwicklungsmethoden
  • Sehr gute Programmierkenntnisse in einer der Sprachen Java oder C++ oder C# oder PHP. Gute Programmierkenntnisse in einer der anderen Sprachen
  • Sicherer Umgang mit CSS, JavaScript, XML, DOM/DHTML, Subversion, Webservices, MySQL und Entwicklungsumgebungen
  • Kenntnisse agiler Entwicklungsmethoden wie Scrum und Unit-Testing
  • Idealerweise Erfahrung mit moderner Programmiermethodik wie TDD, SOLID, DRY, KISS
  • Abgeschlossenes Hochschulstudium der Informatik, Naturwissenschaften, Ingenieurwissenschaften oder vergleichbare Qualifikation mit mindestens einjähriger Berufserfahrung
  • Sehr gute Deutsch- und gute Englischkenntnisse.
Die Deutsche Messe stellt im B2B-Umfeld Kontakt zwischen Herstellern und Interessenten her. Dazu dienen die großen Präsenzmessen CeBIT, HANNOVER MESSE und viele andere. Die Deutsche Messe Interactive, eine Tochter der Deutschen Messe setzt das Business der Messe im Netz fort. Die DMI führt Anbieter und Geschäftskunden über das Internet zusammen. Durch enge Verzahnung mit den Marketing- und Vertriebssystemen der Hersteller wird der Wert solcher Kontakte wirtschaftlich messbar. Kein Spam, keine New Economy, keine Handelsplattform, sondern echte Business Leads.

Arbeitsort: Hannover oder Hamburg
Beginn: je früher desto besser
Sicherheit: ja, das Startup ist solide finanziert (kein VC)

Schreibt mir an: heiner.wolf@messe-interactive.de
Schickt mir eine Telefonnummer und ein kurzes Profil. Ich rufe zurück.

15. August 2010

Entwickler Kennenlernen

Bei Startups ist das Team meistens klein. Da hängt der Erfolg des Unternehmens von jedem Einzelnen ab. Deshalb versuchen wir immer wieder ein starkes Team zusammen zu stellen, das alle Entwicklungsherausforderungen meistern kann.


Am Anfang ist es sehr schwer Entwickler/innen einzuschätzen. Der eine behauptet, eine Programmiersprache zu kennen, hat sie aber nur in der Vorlesung gesehen. Die andere gibt an "nur so ein bisschen zu programmieren", aber nicht richtig. Später kommt heraus, dass sie die Benutzerverwaltung für das Wohnheim als Webanwendung nebenbei gemacht hat und auch noch eine iPhone App dafür.

Und dann gibt es noch so viele Technologien. Keiner kann alles abdecken. Es ist fast unverschämt eine Web-Entwicklerin nach XAML zu fragen oder einen Hobby-Gamemodder, der gerade von der Schule kommt, nach Scrum. Trotzdem haben alle, die offen, aktiv und selbstmotiviert sind, das Potential großartige Developer zu sein.

Aber irgendwo muss ja anfangen. Deshalb hier meine kurze Liste von Themen, die mich brennend interessieren, wenn ich jemand von der programmierenden Menschheit kennen lernen will.

1. Technologie

Wie gut würden Sie Ihre Fähigkeiten als Programmierer/in einschätzen.
Auf der Skala von:
- Thema bekannt (gelesen, gehört, Vorlesung in der Uni)
- Etwas Praxis (probiert, Übungsaufgabe, mal verwendet)
- Viel Erfahrung (Profi-Level, kenne ich ziemlich gut)
- Ausgezeichnet (Wizard-Level, könnte das Ding selber schreiben)

Wizard-Level bedeutet, z.B. bei XML einen XML Parser selbst zu schreiben, nicht "nur" einen XML Parser zu benutzen. Wizard-Level heißt den PHP Interpreter selber schreiben können, einen HTTP-Server, JUnit nicht nur benutzen, sondern eine alternative Unit Test Library selbst schreiben

Java, C#
MySQL
HTTP
HTML/CSS
SOAP
XMPP
JSON
OAuth
TCP/IP
boost, STL
Eclipse
CVS, Subversion, Git
Win32, MFC, COM, XAML
3D-Engines, welche?
Selenium
PHP, Python, Ruby on Rails, Perl
MS SQL Server, Oracle
XML
JavaScript
REST
Ajax
COMET, BOSH
Objective-C , Scala, Groovy, Erlang
C, C++
gcc
Profiling
EC2, S3, SQS
wxWidgets, Qt, Gtk
Maven, Ant, Hudson/Jenkins
Spring, Hibernate
Javascript Libraries, jQuery, ExtJS, andere?
Netzwerk Programmierung, sockets, andere?
Concurrency, Mutex, pthread, andere Thread-APIs?
Assembler, welche?
DevStudio, welche Versionen?
Text Editoren, was verwenden Sie zum Programmieren/Scripting?
Web-Server, Application Server, Tomcat, Apache, andere?
Template Engines, welche?
Caches, Memcache, Redis, Terracotta, andere?
Browser Extensions, für welche Browser?
Unit Test Frameworks, JUnit, NUnit, andere?
Logging Frameworks, log4net, log4j, andere?

2. Methodik
Wie gut kennen und wenn ja, seit wann verwenden Sie:

Objektorientierte Entwicklung
Agile Entwicklung
TDD
BDD
SOLID
DRY
MVC
Refactoring
Unit Tests
Automatisiertes UI Testing
Automatisierte Integrationstests
Code Coverage Analyse
Coding Conventions
Frequent Releases, wie "frequent"?
Pair Programming
Software Design Patterns
Scrum als Developer, Scrum Master, PO
Refactoring- und Coding-Werkzeuge in Entwicklungsumgebungen

3. Allgemein

Haben Sie Computer zuhause?
Welche(s) Betriebssystem(e)?
Einen Rechner oder ein Netzwerk?
Haben Sie eine Website? welche URL?
Bloggen, Twittern Sie oder benutzen Sie andere Social Networks?
Können Sie Linux installieren und verwalten? Welche Distribution?
Auf welchen Plattformen programmieren Sie? Windows, Mac, Linux, iOS?
Haben Sie Cross-Plattform Erfahrung?
Programmieren Sie gerne?
Programmieren Sie viel? wie viel? gut? sehr gut?
Haben Sie an Open-Source Projekten mitgearbeitet? welche?
Gibt es öffentlich zugängliche Projekte? URL?
Können Sie Code oder andere Arbeitsproben zeigen?

2. August 2010

Tokyo Impressions

Brooklyn bridge and Statue of Liberty. A view from across the bay of Tokyo back to the Tokyo skyline (part of it). The skyline of Tokyo goes around the bay, very impressive.

The view is from Daiba, a resort complex with shops, restaurants, artificial woods and beautiful sand beach. There are restaurant boats slowly moving across the bay's arm. What looks like the Brooklyn bridge is actually the Rainbow bridge.
On Sunday I did the tourist thing: visiting temples, shrines, markets and the big shopping quarters.


At a budism temple - for a 100 yen contribution -I got a look at my future fortune. By chance (or maybe not) I seemed to be the luckiest guy.

This paper says "Best fortune: your dream will come true, if sick will heal quickly, person I am waiting for will come". The locals say, that this is the best one can get.

Lets see what the future holds.
The big KLab 10 year anniversary party. All 200 employees where there. The COO was DJ with hoody (Kaputzenpulli), his normal office dress. CEO gave a cool show on the stage. Lots of entertainment including the company's own girl band (!). People are very kind. I liked it very much.

Alcohol for free like beer, whisky. Unfortunately no RedBull for the wodka available. Started with Coke. Later I specialized on "umeshu rokku", apricot liquor on the rocks. Just say to the bar keeper: "umeschulokku".

Tokyo by night on the way back.

Just like any other city for a small person in a big street. But clean and very safe.

This was a good week.

Cya

29. Juli 2010

IBM recommends XMPP for Realtime Web Apps


There is a new tutorial from IBM about how to build modern realtime web apps. In the tutorial IBM suggests using XMPP, BOSH from JavaScript. It is worth reading.

http://www.ibm.com/developerworks/xml/tutorials/x-realtimeXMPPtut/index.html

This is exactly how weblin.lite was built 2 years. Even including the HTTP proxy to circumvent the JavaScript security limitation, tunneling XMPP through HTTP with BOSH, using a real XMPP server for message routing and a JavaScript XMPP client library to communicate. Also: jQuery, Ajaj, XML, JSON, WebServices, mysql. Basically, all the cool web-tech stuff we like.

Congrats to the weblin dev team. The best dev team I've ever had.

_happy_boshing()

Yes, we have been there. Now it is so much a standard, that IBM recommends the technology. It will be picked up by many others and we are already the experts. So much for certain ignorant investors and business angels, who do not recognize technology in their portfolio, even if it jumps into their face. We will be there without you.

23. Juli 2010

Vorbereitung für Tokio

Morgen Samstag 13:55 fliege ich von von Hamburg nach Frankfurt. Nach 5 h Aufenthalt (war billiger) von Frankfurt nach Tokio. Komme dort Sonntag
15 h Ortszeit an.

Tokio hat 7 h Unterschied zu Schland. Wenn hier 10 h ist, ist dort schon 17 h. Die Japaner sind uns was voraus. Ich werde da 3 Wochen sein. Und es wird heiss. Habe viele T-Shirts dabei.

Treffe in Tokio einen alten Freund aus Weblin-Zeiten. Mal sehen was da in Japan so geht Das wird ein Spass. Und ein Abenteuer - lost in translation.

happy_traveling()