Get Started With Ejabberd

Installation

Before installing ejabberd make sure you have Erlang environment set up. Run the following command and verify the output

$erl -version Erlang (ASYNC_THREADS,HIPE) (BEAM) emulator version 5.10.1  I used to install ejabberd with apt-get command, which is convenient but always several versions behind. That’s why I switched to building from sources. All scripts below are assumed to be run under ejabberd user. First, create a directory where all ejabberd versions will be installed, if it does not exist yet $ sudo mkdir /opt/ejabberd
$sudo chown -R ejabberd /opt/ejabberd  Download the sources $ cd
$git clone git@github.com:processone/ejabberd.git$ cd ejabberd


Select version you want to install by executing git branch -a and git tag --list commands. Let assume we want to install version 2.1.12 from branch 2.1.x

$git checkout 2.1.x$ cd src


The next step is optional. If you are going to integrate ejabberd with RabbitMQ, you need to download the source of rabbitmq-xmpp module

$wget https://raw.github.com/ndpar/rabbitmq-xmpp/rabbitmq3/src/mod_rabbitmq.erl$ wget https://raw.github.com/ndpar/rabbitmq-xmpp/rabbitmq3/src/rabbit.hrl


Now we are ready to install ejabberd. To see all available configuration options, run ./configure --help.

$./configure --prefix=/opt/ejabberd/ejabberd-2.1.12 --enable-user=ejabberd$ make
$make install$ cd /opt/ejabberd
$ln -s ejabberd-2.1.12 ejabberd  Configuration Ejabberd comes with reasonable default configuration. Only two lines need to be changed to make it work in your environment. Open /opt/ejabberd/ejabberd/etc/ejabberd/ejabberd.cfg file and find SERVED HOSTNAMES section. By default Ejabberd is configured for localhost only. Change it to your machine’s DNS name. Here is what I have in my config The second thing we need to do is to configure admin user. Here is mine, registered for the host I just defined Save the config file and start the server $ /opt/ejabberd/ejabberd/sbin/ejabberdctl start


You can quickly check the log file to see if the server has been started successfully

$less /opt/ejabberd/ejabberd/var/log/ejabberd/ejabberd.log  If it wasn’t, you might want to enable debug logs and restart the server to see more details $ /opt/ejabberd/ejabberd/sbin/ejabberdctl restart


Registering users

The first (admin) user has to be registered in command line

$cd /opt/ejabberd/ejabberd/sbin$ ./ejabberdctl register andrey jabber.ndpar.com ******


This user is the same as admin you configured in the previous section. If you go to localhost:5280/admin in the browser, you should be able to login with the same password you registered the user

To really enjoy IM you need more users on your server. The best part here is that you can create new users just from your Jabber client. Simply go to File -> your ejabberd account -> Add User

For other available options please consult official documentation.

State Machine in Erlang

There is some sort of confusion in the object-oriented community about functional languages. How is it possible to implement stateful application if the language has no concept of state? It turns out that it’s actually quite possible, although the solution is completely deferent from what we see in the OO realm. In Erlang, for example, state can be implemented by using process message passing and tail recursion. This approach is so elegant that after you’ve learned it, the OO way of doing this looks unnatural. The code below is the Erlang implementation of Uncle Bob’s FSM example. Look at it. Isn’t that code clean and expressive? It looks almost like DSL but it’s actually regular Erlang syntax.

The idea behind this code is simple. Every state is implemented as a function that does two things: it listens for messages sent by other processes; when message is received the appropriate action is taken and one of the state-functions called recursively. Simple.

Parsing Files Using Groovy Regex

In my previous post I mentioned several ways of defining regular expressions in Groovy. Here I want to show how we can use Groovy regex to find the data in the files.

Parsing properties file (simplified)1

Data: each line in the file has the same structure; the entire line can be matched by single regex.

Task: transform each line to the object.

Solution: construct regex with capturing parentheses, apply it to each line, extract captured data.

Demonstrates: File.eachLine method, matrix syntax of Matcher object.

Parsing CSV files (simplified)2

Data: each line in the file has the same structure; the line consists of the blocks separated by some character sequence.

Task: transform each line to the list of objects.

Solution: construct regex with capturing parentheses, parse each line with the regex in a loop extracting captured data.

Demonstrates: ~// Pattern defenition, Matcher.group method, \G regex meta-sequence.

Finding snapshot dependencies in the POM (simplified)3

Data: file contains blocks with known boundaries (possibly spanning multiple lines).

Task: extract the blocks satisfying some criteria.

Solution: read the entire file into the string, construct regex with capturing parentheses, apply the regex to the string in a loop.

Demonstrates: File.text property, list syntaxt of Matcher object, named capture, global \x regex modifier, local \s regex modifier.

Finding stacktraces in the log

Data: file contains entries each of which starts with the same pattern and can span multiple lines. Typical example is log4j log files:

2009-10-16 15:32:12,157 DEBUG [com.ndpar.web.RequestProcessor] Loading user
at org.springframework.orm.hibernate3.HibernateTemplate$1.doInHibernate(HibernateTemplate.java:531) at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:419) at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374) at org.springframework.orm.hibernate3.HibernateTemplate.get(HibernateTemplate.java:525) at org.springframework.orm.hibernate3.HibernateTemplate.get(HibernateTemplate.java:519) at com.ndpar.dao.UserManager.getUser(UserManager.java:90) ... 62 more 2009-10-16 15:32:14,659 DEBUG [com.ndpar.jms.MessageListener] Received message: ... multi-line message ... 2009-10-16 15:32:15,169 INFO [com.ndpar.dao.UserManager] User: ...  Task: find entries satisfying some criteria. Solution: read the entire file into the string4, construct regex with capturing parentheses and lookahead, split the string into entries, loop through the result and apply criteria to each entry. Demonstrates: regex interpolation, combined global regex modifiers \s and \m. Resources Footnotes 1. This example is for demonstration purposes only. In real program you would just use Properties.load method. 2. The regex is simplified. If you want the real one, take a look at Jeffrey Friedl’s example. 3. Again, in reality you would find snapshots using mvn dependency:resolve | grep SNAPSHOT command. 4. This approach won’t work for big files. Take a look at this script for practical solution. Groovy Regular Expressions Because of the compact syntax regular expressions in Groovy are more readable than in Java. Here is how Jeffrey Friedl’s example looks in Groovy: As you can see, there are several notations, and for every subexpression you can choose the one that is most expressive. Resources Split Commits in Git $ git log # copy commit_id
$git rebase -i <commit_id>^ # choose edit$ git reset HEAD^
$git add -i # loop through files; patch or update$ git ci