Apache Camel not only is one of my favourite frameworks ever but it also allows the humble developer to create a full blown chat bot within a few lines of code and using the Camel XMPP component.

In the following tutorial, we’re going to create a simple chat bot and since Atlassian’s HipChat basic plan is now free for unlimited users, we’re using HipChat as our play- and testing ground for the bot.

bot on hipchat in action
Figure 1. XMPP Bot connected to HipChat

Project Setup / Dependencies

Using Maven, we’re adding three dependencies to our pom.xml: Camel Core, Camel XMPP Components and Config-Builder for our configuration management.

<dependency>
	<groupId>org.apache.camel</groupId>
	<artifactId>camel-core</artifactId>
	<version>2.14.0</version>
</dependency>
<dependency>
	<groupId>org.apache.camel</groupId>
	<artifactId>camel-xmpp</artifactId>
	<version>2.14.0</version>
</dependency>
<dependency>
	<groupId>com.tngtech.java</groupId>
	<artifactId>config-builder</artifactId>
	<version>1.3</version>
</dependency>

We’re using Camel with Java in this tutorial – but if you prefer using Scala, porting the following examples shouldn’t be a problem – please feel free to have a look at my blog article "Using Apache Camel with Scala and the Camel Scala DSL" for further details about the Camel Scala DSL.

HipChat Setup (optional)

HipChat with the basic plan is free with unlimited users and no need to enter credit card information or stuff like this.

So basically to create a HipChat instance for our bot we need to do..

  • Register a new account at https://www.hipchat.com/sign_up

  • Create a new room

  • Create a user account for the bot

  • Make sure, that the bot-account may access the room

That’s all …

Creating the Bot

Now that the playground for our bot conversations is ready we’re ready to write the bot application with a few lines of code.

Managing Configuration

First of all, we’re using a property file to hold our configuration details. To access this information, I’m using the config-builder library here that allows us to bind fields of a POJO to the elements of the properties file using simple annotations.

If you’re interested in some more details here, please feel free to have a look at my blog article “Using Java Config-Builder to assemble your Application Configuration“.

This is our configuration class:

package com.hascode.app;

import com.tngtech.configbuilder.annotation.propertyloaderconfiguration.PropertiesFiles;
import com.tngtech.configbuilder.annotation.valueextractor.PropertyValue;

@PropertiesFiles("config")
public class Config {
	@PropertyValue("port")
	private final int port = 5222;

	@PropertyValue("host")
	private String host;

	@PropertyValue("user")
	private String user;

	@PropertyValue("password")
	private String password;

	@PropertyValue("room")
	private String room;

	@PropertyValue("nickname")
	private String nickname;

	// getter, setter ommitted ...
}

This is our config file src/main/resources/config.properties fill the valid properties according to your environment or HipChat account:

user=12345_67890
nickname=hasCode Bot
password=ohiamsoosecret
host=chat.hipchat.com
port=5222
room=12345_bot_test

*Update:* We may obtain all values for our property file from the HipChat configuration (being logged in as administrator):

  • user: Account Settings → XMPP/Jabber Info → Username

  • password: The user account password

  • host:Account Settings → XMPP/Jabber Info → Account info → Connect host

  • port:Account Settings → XMPP/Jabber Info → Account info → Connect port

  • room:Account Settings → XMPP/Jabber Info → Account info → Connect host

Bot Logic and Camel Routes

Basically we’re doing all the work with a single route. We’re able to create an XMPP endpoint using an URL like this: “xmpp://user@host:port?room=chatroom&password=xxx&nickname=Bot“.

When a new message arrives from the XMPP endpoint we’re first filtering for messages containing a valid bot command – valid commands are:

  • bot date: displays the current date

  • bot help: displays a usage hint

Having filtered the chat messages for valid bot commands, we’re now using a content-based-router to delegate to the appropriate command handling.

Finally we’re sending some output to the XMPP endpoint so that the bot talks to the designated HipChat room.

package com.hascode.app;

import java.time.Instant;

import org.apache.camel.Exchange;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.xmpp.XmppMessage;
import org.apache.camel.main.Main;
import org.jivesoftware.smack.packet.Message;

import com.tngtech.configbuilder.ConfigBuilder;

public class Bot {
	public static void main(final String[] args) throws Exception {
		new Bot().run();
	}

	private void run() throws Exception {
		Config config = new ConfigBuilder<Config>(Config.class).build();
		String chatEndpoint = String.format("xmpp://%s@%s:%s?room=%s&password=%s&nickname=%s", config.getUser(), config.getHost(), config.getPort(), config.getRoom(), config.getPassword(),
				config.getNickname());

		Main main = new Main();
		main.addRouteBuilder(new RouteBuilder() {
			@Override
			public void configure() {
				from(chatEndpoint)
				.filter(exchange -> isValidBotCommand(exchange))
				.choice()
					.when(exchange -> getSmackMessage(exchange).getBody().contains("date"))
						.setBody(constant("It's " + Instant.now()))
						.to(chatEndpoint)
					.otherwise()
						.setBody(constant("Available commands: bot date, bot help"))
						.to(chatEndpoint);
			}
		});
		main.enableHangupSupport();
		main.run();
	}

	private boolean isValidBotCommand(final Exchange exchange) {
		return getSmackMessage(exchange).getBody().matches("bot (date|help)");
	}

	private Message getSmackMessage(final Exchange exchange) {
		XmppMessage xmppMessage = (XmppMessage) exchange.getIn();
		Message smackMessage = xmppMessage.getXmppMessage();
		return smackMessage;
	}

}

The Bot in Action

Running the bot should not be a problem, we simply need to fill the config.properties with our account information and should afterwards be able to do some bot-conversation as shown in the following screen-shot.

Run it from your IDE or using the following Maven command:

mvn compile exec:java -Dexec.mainClass=com.hascode.app.Bot
bot on hipchat in action
Figure 2. XMPP Bot connected to HipChat

Tutorial Sources

Please feel free to download the tutorial sources from my GitHub repository, fork it there or clone it using Git:

git clone https://github.com/hascode/camel-hipchat-bot.git

Article Updates

  • 2014-11-04: Added Maven snippet to run the bot.

  • 2015-05-19: Detailed information about settings and configuration details added.

  • 2015-06-17: Details about running the bot with Maven added.