# Smack: A Minimal Working Example (in Java)

## Introduction

This document provides a minimal working example of a client implementation using the Smack library, making it connect to a running Openfire server.

Topics that are covered in this document:

## Background

Ignite Realtime's Smack project is an Open Source XMPP client library for instant messaging and presence. A pure Java library, it can be embedded into your applications to create anything from a full XMPP client to simple XMPP integrations such as sending notification messages and presence-enabling devices.

This guide describes how to use Smack to connect to Openfire. It provides nothing more than a minimal working example, intended as a stepping stone to for client developers that get started with a new project.

## Preparations

In this example, a client connection will be made against a running Openfire server. For ease of configuration, the 'demoboot' setup of Openfire is used.

The 'demoboot' setup of Openfire allows one to start a fresh installation of Openfire into a certain provisioned state, without running any of the setup steps. When running in 'demoboot' mode:

- an administrative account is created using the username 'admin' and password 'admin'
- three users are automatically created: 'jane', 'john' and 'juan' (all using the value 'secret' as their password)
- the XMPP domain name is configured to be 'example.org' (for ease of use, configure 'example.org' to be an alias of '127.0.0.1' in your hosts file!)

To start Openfire in 'demoboot' mode, you can invoke the Openfire executable using the `-demoboot` argument, as shown below.

Starting Openfire in 'demoboot' mode.

    $ ./bin/openfire.sh -demoboot

That should be everything that you need to get Openfire running. Background information on the 'demoboot' mode can be found in Openfire's Demoboot Guide.

## Code

This example uses Apache Maven to define the project and define usage of the Smack library. Other build tools, like Gradle, could also be used.

To start the project, create a Maven `pom.xml` file in the root of your project. This file is primarily used to define the Smack library as a dependency of the project.

Example pom.xml file

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>

        <groupId>org.igniterealtime.demo</groupId>
        <artifactId>smack-minimal-working-example</artifactId>
        <version>1.0-SNAPSHOT</version>

        <description>A minimal working example of a Smack-based client.</description>

        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>

        <dependencies>
            <dependency>
                <groupId>org.igniterealtime.smack</groupId>
                <artifactId>smack-java8-full</artifactId>
                <version>4.4.6</version>
            </dependency>
        </dependencies>

    </project>

A simple Java class file, using nothing but a `main` method, will be used to create two XMPP connections that connect to Openfire. One connection will start listening for a chat message, while the other connection will send such a message.

Example class file

    import org.jivesoftware.smack.ConnectionConfiguration;
    import org.jivesoftware.smack.filter.MessageWithBodiesFilter;
    import org.jivesoftware.smack.packet.Message;
    import org.jivesoftware.smack.packet.MessageBuilder;
    import org.jivesoftware.smack.tcp.XMPPTCPConnection;
    import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;

    import java.time.Duration;

    public class TestClients
    {
        public static void main(String[] args) throws Exception
        {
            //SmackConfiguration.DEBUG = true;

            final XMPPTCPConnectionConfiguration configSender = XMPPTCPConnectionConfiguration.builder()
                .setUsernameAndPassword("john", "secret")
                .setXmppDomain("example.org")
                .setResource("test")
                .setHost("localhost")
                .setPort(5222)
                .addEnabledSaslMechanism("PLAIN")
                .setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
                .build();

            final XMPPTCPConnectionConfiguration configReceiver = XMPPTCPConnectionConfiguration.builder()
                .setUsernameAndPassword("jane", "secret")
                .setXmppDomain("example.org")
                .setHost("localhost")
                .setPort(5222)
                .addEnabledSaslMechanism("PLAIN")
                .setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
                .build();

            final XMPPTCPConnection connectionSender = new XMPPTCPConnection(configSender);
            final XMPPTCPConnection connectionReceiver = new XMPPTCPConnection(configReceiver);

            try
            {
                connectionSender.setUseStreamManagement(false); // To reduce output in the debug log.
                connectionReceiver.setUseStreamManagement(false); // To reduce output in the debug log.

                connectionSender.connect();
                connectionReceiver.connect();

                connectionSender.login();
                connectionReceiver.login();

                Thread.sleep(Duration.ofSeconds(2).toMillis());

                // Listen for incoming messages.
                connectionReceiver.addAsyncStanzaListener((stanza -> System.out.println("Received: " + ((Message) stanza).getBody())), MessageWithBodiesFilter.INSTANCE);

                // Construct and send message.
                final Message message = MessageBuilder.buildMessage()
                    .to(connectionReceiver.getUser())
                    .setBody("Hello!")
                    .build();
                connectionSender.sendStanza(message);

                Thread.sleep(Duration.ofSeconds(2).toMillis());
            }
            finally
            {
                connectionSender.disconnect();
                connectionReceiver.disconnect();
            }
        }
    }

Use your IDE to run the `main` method. You should see `Received: Hello!` be printed to the standard output. That's it!

Note that this example disables important security features. You should not use this for anything important!

## Further Reading

Please use the links below to find more information.

- Smack project home page
- Smack Wiki
- Smack READMEs (and upgrade guides)