Trucs de geek

Atompub interface for distributed microblogging over XMPP

Posted on septembre 12, 2008

atompubsub has been updated and simplified and renamed to atommicroblog. Some might argue that it’s useful now.

The scope of the plugin is reduced to one node : the “urn:xmpp:microblog” node of the upcoming Microblogging over XMPP XEP.

Also improved : removed dependency on Yaws and implemented caching like they want it.

The code is on the ejabberd_modules svn.

For full context, these mails tell about production use.

Once this patch is implemented, it’s going to be even better. I will move entry payload processing into a nodemacroblog. And maybe I’ll find a more generic interface for atommicroblog.erl.

To the broader subject of distributed microblogging over XMPP, you might want to read Jack Moffit’s blog post. Follow the links !

PS : Yup, very pompous title.

Auth me on Jabber

Posted on mars 07, 2008

CAS est un service très populaire permettant de mettre en place le Single Sign On, avec des librairies clientes pour la plupart des langages.

On peut facilement rajouter des handlers d’authentification.

En voici un très rapide, permettant de s’authentifier sur un service Jabber.

Installation :

Uniquement compatible CAS v3.

Installez ce bout de xml dans le deployerConfigContext, dans la liste des AuthHandlers :


<bean class="com.ohmforce.cas.JabberAuthenticationHandler">
 <property name="jabberHostname" value="DOMAIN"/>
</bean>

Copiez jabber-cas.jar.zip et la jar de Smack, relancez la webapp CAS et c’est tout.

Pour se logger sur vos applications CASifiées, vos utilisateurs utiliserons leur compte défini dans sur le domaine indiqué par jabberHostname, le mal nommé.

Le code

Y en a tellement peu que ca tient ici.


package com.ohmforce.cas;
import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;

final public class JabberAuthenticationHandler extends
        AbstractUsernamePasswordAuthenticationHandler {
    private String jabberHostname;
    @Override
    protected boolean authenticateUsernamePasswordInternal(
            UsernamePasswordCredentials credentials)
            throws AuthenticationException {
        XMPPConnection conn = new XMPPConnection(jabberHostname);
        try {
            conn.connect();
            conn.login(credentials.getUsername(), credentials.getPassword());
        } catch (XMPPException e) {
            log.error("Failed", e);
            return false;
        }
        finally{
            conn.disconnect();
        }
        return true;
    }

public void setJabberHostname(String server)
{
    jabberHostname=server;
}
public String getJabberHostname()
{
    return jabberHostname;
}

}

Bonnes résolutions

Posted on janvier 04, 2008

Pour commencer, bonne année et meilleurs vœux pour cette nouvelle année !

Les résolutions professionnelles (les autres, je les garde pour moi)

Exercice obligatoire en cette période de l’année, une liste de résolutions. Avec un bilan en fin d’année 2008 (c’est ma première résolution, tiens, faire un bilan à la fin de l’année)

MangerVite sur mon iPhone

Peu de temps l’année passée pour fignoler MangerVite …

Toutefois une version iPhone me semble super indispensable, et j’ai envie de faire un peu de développement web pour cette plate-forme.

Parenthèse sur l’iPhone : pouvoir lire ses flux RSS dans le métro, priceless ! En bon utilisateur de NetNewsWire, j’apprécie l’intégration avec le version iPhone de NewsGator : mes flux sont synchronisés entre le téléphone et le MacBook Pro, et c’est bien pratique :)

XMPP

Je vais continuer à travailler dessus. Un client développé avec Jiggy ? (oui, toujours pour iPhone, il est vrai que je suis assez emballé par ce téléphone).

Je vais aussi, mais c’est plus difficile, continuer de convertir du OhmMan à Jabber, pour finir par me débarrasser d’IRC. (let’s kill this beast !)

J’ai installé un ejabberd sur un serveur d’ohmforce, avec authentification LDAP, et remplissage automatique du roster avec la liste des OhmMen. Il me reste des problèmes d’encodage à régler avec la passerelle IRC, mais vu que j’ai corrigé le problème sur cestari.info, y a pas de raisons :)

Sur le protocole, il faut que je bosse sur pubsub, vu que j’ai pas réussi à faire tourner quoique ce soit d’intéressant (les exemples XMPP4R ne tournent pas avec ejabberd pre-2.0.0)

Java

  • Evaluer GlassFish

  • Alfresco, en repository de documents avec workflow, multilingue et versionning, le tout accessible en ReST. Sexy beast. Il faut que je passe du temps dessus.

  • Grails et Groovy … je ne sais pas. J’étais assez emballé, jusqu’à ce que je m’y mette un peu. Le temps perdu par l’exécution des scripts (oui, il faut bien qu’elle démarre, cette JVM, et JRuby a le même problème) m’a bien refroidi, et je trouve la syntaxe de ruby tellement plus agréable …

Erlang

Faut que je repasse un peu de temps dessus, pour affiner mod_rpc, et l’utiliser :)

[UPDATED] XMPPPool : XMPP Connection Pooling for Tomcat and Grails/Jetty

Posted on septembre 10, 2007

Release 0.3 of XMPPPool

[Update : also added support for Grails Jetty]

[Update 2 : Simplified the API a lot. It is now basically invisible …]

About

It provides XMPP connection pooling for Tomcat, configured as a resource in the $TOMCAT_HOME/conf/server.xml.

The main use case to use Groovy Jabber-RPC, with the webapp acting as a client :

  • You fetch a XMPPConnection from the pool,
  • call an RPC method,
  • get the result,
  • return the XMPPConnection to the pool.

Of course you can use the code to write XMPP “servers”/bots, but you’ll have to manage the lifecycle of the connection (i.e. launch a separate thread)

How it works

A pool is created, with connections to the XMPP server. All connections use the same XMPP account, but each have a unique resource.

Rule 10.5 of RFC 3920 (XMPP Core) means that is a stanza is sent to a JID with a specific resource, it MUST be delivered to this resource or it MUST fail. However if a stanza is sent to a jid without any resource identifier, it SHOULD be sent to at least one of the resources.

So make sure that the code answering to a query coming from an XMPPPool managed connection sends it to a specific JID.

Quick install guide for Tomcat

Download XMPPPool-0.3.0-jar-with-dependencies.jar.zip and copy it in your $TOMCAT_HOME/common/lib. Then in server.xml, configure your source as follow :


<Resource auth="Container" maxActive="10" maxIdle="5" maxWait="10000" 
  factory="com.ohmforce.xmpp.XMPPSourceFactory" type="com.ohmforce.xmpp.XMPPConnectionPool" name="xmpp/connection"
  username="username" password="pass" service="localhost" port="5222"/>

The pooling code is using commons-pool from Apache. All the usual options are available. port is optional and defaults to 5222.

Now restart your container.

Quick install guide for Grails/Jetty

First you need to patch Grails as per this report (which should be implemented soon in Grails). Don’t forget to add the jars to $GRAILS_HOME/lib!

Also unzip and add XMPPPool-0.3.0-jar-with-dependencies.jar in GRAILS_HOME/lib

Then add a jetty-env.xml file in WEB-INF/ directory (of your Grails app)


<Configure class="org.mortbay.jetty.webapp.WebAppContext">
  <New id="xmpp" class="org.mortbay.jetty.plus.naming.Resource">
    <Arg>xmpp/connection</Arg>
    <Arg>
    <New class="com.ohmforce.xmpp.XMPPSourceFactory">
     <Set name="properties">
       <New class="java.util.Properties">
         <Put name="username">username</Put>
         <Put name="password">pass</Put>
         <Put name="service">localhost</Put>
       </New>
      </Set>
   </New>
 </Arg>
   </New>
</Configure>

Start the grails app : grails -Denable.jndi=true run-app

Now inside a grails controller you can connect to a Jabber-RPC service :

Using from Grails :

Now inside a grails controller you can connect to a Jabber-RPC service :


import javax.naming.InitialContext;
import groovy.net.xmlrpc.*
class HelloController{
def hello = {
        def p =new InitialContext().lookup("java:comp/env/xmpp/connection")
        def serverProxy = new JabberRPCServerProxy(p, "cstar@localhost")
        def s = serverProxy.add(2,6)
        def e = serverProxy.echo("toto")
        flash.message = "${s} and ${e}"
        p.disconnect() // does not actually disconnect, but returns connection in pool
    }
}

The server code (slightly modified from the examples on the Groovy website. fixed typos and updated to latest Smack version) :


import groovy.net.xmlrpc.*
import org.jivesoftware.smack.XMPPConnection
def server = new JabberRPCServer()
server.echo = {return it+"toto"} 
server.add = {i,j -> return i+j} 
def serverConnection = new XMPPConnection("localhost")
serverConnection.connect() 
serverConnection.login("user", "pass") 
server.startServer(serverConnection)

Using the datasource in a servlet


try{
    InitialContext ctx = new InitialContext();
    XMPPConnection conn = (XMPPConnection) ctx.lookup("java:/comp/env/xmpp/connection");
    // Do things here
    conn.disconnect(); // does not actually disconnect, but returns connection in pool
}
catch(Exception e){
    e.printStackTrace();
}

For actually using the connection, please refer to the Smack developper guide

Building the source code

The project is built with Maven.

mvn assembly:assembly

cp target/XMPPPool-0.3.0-jar-with-dependencies.jar $TOMCAT_HOME/common/lib/

And you’re set.

Bugs ? Patches ?

  • mail : eric at ohmforce dot com
  • xmpp : cstar at cestari dot info

Known issues

  • Only one pool can be configured on a given tomcat instance (Although that should fit most use cases)

Todo

  • Better error reporting, I guess :)

License

Apache 2.0 license, the same as Smack and others libs XMPPPool is built upon. Free to use, as long as you don’t sue me or remove my name from the code …

Download