Smack , XMPP and GTalk

I had to work on project which supports P2P file transfer and it is then when i thought that why not use an existing framework rather than building new one from scratch.

I have worked on Smack/ Openfire  XMPP libraries around 6 years ago and Revisited the same for the above purpose

Jabber /XMPP server’s support P2P File transfer protocol’s and follow Jingle Specification. So i thought to testing how to use smack api to build a Chat client in java. Next tutorial i’ll illustrate the same from Flex/Flash

Here is sample code that can connect to GoogleTalk server and gets list of all friends.  This also shows example of how to Send a chat message to a given user.

Here are few Terms you need to understand before you start using XMPP libraries

Roster

Roster is the name given to the list of contacts which appears in one’s chat client. In Google Talk terms, it is the list of friends you would see once you login. The elements of the roster are your contacts. Each of these items is identified by a unique identifier called JID (Jabber Identifier).

Rosters are stored on the server so that the XMPP client may retrieve the same each time the user logs in.

Message

This is one of the three fundamental Stanzas in XMPP. (The other two are IQ and Presence.) Just as it is obvious, a Message Stanza is used for sending IMs (Instant Messages).

IQ

This is another very important Stanza. IQ stands for Info/Query. It is similar to traditional Request/Response paradigms such as HTTP. An IQ Stanza can be one of four types, “get”, “set”, “result” or “error”. The first two are requests or queries while the last two are responses or information. An IQ Stanza can wrap various kinds of elements. Let’s see one such example here.

Juliet logs onto her XMPP client. The client sends an XMPP IQ Stanza of type “get” to gmail.com server requesting her roster.
<iq from=”ashwin@gmail.com” type=”get” id=”roster_1″> <query xmlns=”jabber:iq:roster”/> </iq>

Presence

This is the third Stanza type specified by XMPP Core. In layman’s terms, Presence simply refers to the availability or status of a contact.

Now that you are familiar with some basic terms you will come across the library, i’ll start pasting some working code which can be tested against gtalk

Sample HelloWorld Code

<pre>

package com.linkwithweb.demos;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;

/**
 * @author Ashwin Kumar
 *
 */
public class HelloWorld {
	static JabberSmackAPI api = new JabberSmackAPI();

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		connectTOGTalk();
	}

	/**
	 *
	 */
	private static void connectTOGTalk() {
		// Create XMPP connection to gmail.com server
		XMPPConnection connection = new XMPPConnection("gmail.com");

		try {
			// You have to put this code before you login(Required for Gtalk and not for Jabber.org)
			SASLAuthentication.supportSASLMechanism("PLAIN", 0);
			// Connect
			connection.connect();

			// Login with appropriate credentials
			connection.login("madnesstestuser@gmail.com", "madnesstestuser");

			// Get the user's roster
			Roster roster = connection.getRoster();

			// Print the number of contacts
			System.out.println("Number of contacts: " + roster.getEntryCount());
			api.setConnection(connection);
			// Enumerate all contacts in the user's roster
			for (RosterEntry entry : roster.getEntries()) {
				System.out.println("User: " + entry.getUser());
				if (entry.getUser().contains("pandumalladi")) {
					Chat chat = connection.getChatManager().createChat(
							entry.getUser(), api);
					chat.sendMessage("Testing Hi");
					api.fileTransfer(
							"C:\\development\\Ashwin\\Jingle\\JitSI\\Test.txt",
							entry.getUser());

				}
			}

			connection.disconnect();
		} catch (XMPPException e) {
			// Do something better than this!
			e.printStackTrace();
		}
	}

	/**
	 *
	 */
	public static void connectToJabber() {
		ConnectionConfiguration cc = new ConnectionConfiguration("jabber.org",
				5222, "jabber.org");
		XMPPConnection connection = new XMPPConnection(cc);
		try {
			connection.connect();

			// You have to put this code before you login
			SASLAuthentication.supportSASLMechanism("PLAIN", 0);

			// You have to specify your Jabber ID addres WITHOUT @jabber.org at the end
			connection.login("your.jabber", "password", "resource");

			// See if you are authenticated
			System.out.println(connection.isAuthenticated());

		} catch (XMPPException e1) {
			e1.printStackTrace();
		}
	}
}

</pre>

Sample utility Class used

<pre>

/**
 *
 */
package com.linkwithweb.demos;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collection;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.filetransfer.FileTransferManager;
import org.jivesoftware.smackx.filetransfer.FileTransferNegotiator;
import org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer;

/**
 * API With some Utitlity Methods
 * @author Ashwin Kumar
 *
 */
public class JabberSmackAPI implements MessageListener {

	XMPPConnection connection;
	private FileTransferManager manager;

	public void setConnection(XMPPConnection connection) {
		this.connection = connection;
		manager = new FileTransferManager(connection);
	}

	public JabberSmackAPI() {
	}

	public void login(String userName, String password) throws XMPPException {
		ConnectionConfiguration config = new ConnectionConfiguration(
				"localhost", 5222, "Work");
		connection = new XMPPConnection(config);

		connection.connect();
		connection.login(userName, password);
	}

	public void fileTransfer(String fileName, String destination)
			throws XMPPException {

		// Create the file transfer manager
		// FileTransferManager manager = new FileTransferManager(connection);
		FileTransferNegotiator.setServiceEnabled(connection, true);
		// Create the outgoing file transfer
		OutgoingFileTransfer transfer = manager
				.createOutgoingFileTransfer(destination);

		// Send the file
		transfer.sendFile(new File(fileName), "You won't believe this!");
		try {
			Thread.sleep(10000);
		} catch (Exception e) {
		}
		System.out.println("Status :: " + transfer.getStatus() + " Error :: "
				+ transfer.getError() + " Exception :: "
				+ transfer.getException());
		System.out.println("Is it done? " + transfer.isDone());
	}

	public void sendMessage(String message, String to) throws XMPPException {
		Chat chat = connection.getChatManager().createChat(to, this);
		chat.sendMessage(message);
	}

	public void displayBuddyList() {
		Roster roster = connection.getRoster();
		Collection<RosterEntry> entries = roster.getEntries();

		System.out.println("\n\n" + entries.size() + " buddy(ies):");
		for (RosterEntry r : entries) {
			System.out.println(r.getName());
		}
	}

	public void disconnect() {
		connection.disconnect();
	}

	public void processMessage(Chat chat, Message message) {
		if (message.getType() == Message.Type.chat)
			System.out.println(chat.getParticipant() + " says: "
					+ message.getBody());
	}

	public static void main(String args[]) throws XMPPException, IOException {
		// declare variables
		JabberSmackAPI c = new JabberSmackAPI();
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String msg;

		// turn on the enhanced debugger
		XMPPConnection.DEBUG_ENABLED = true;

		// Enter your login information here
		c.login("ashwin", "ashwin@123");

		c.displayBuddyList();

		System.out.println("-----");

		System.out
				.println("Who do you want to talk to? - Type contacts full email address:");
		String talkTo = br.readLine();

		System.out.println("-----");
		System.out.println("All messages will be sent to " + talkTo);
		System.out.println("Enter your message in the console:");
		System.out.println("-----\n");

		while (!(msg = br.readLine()).equals("bye")) {
			c.sendMessage(msg, talkTo);
		}

		c.disconnect();
		System.exit(0);
	}

}

</pre>

You can checkout the above mavenized project from SVN test it yourself. Have fun with Jabber

https://linkwithweb.googlecode.com/svn/trunk/XMPP

About these ads

12 Responses to Smack , XMPP and GTalk

  1. Fran Serrano says:

    I get:

    “SASL authentication failed using mechanism PLAIN:
    at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java:325)
    at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:395)
    at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:349)
    at es.devel.surfinity.service.impl.GTalkServiceImpl.login(GTalkServiceImpl.java:93)
    at es.devel.surfinity.service.impl.GTalkServiceImpl.sendMessage(GTalkServiceImpl.java:50)”

    when I try to login against GTalk Service.

    • You have to add this before connecting to Gtalk

      // You have to put this code before you login(Required for Gtalk and not for Jabber.org)
      SASLAuthentication.supportSASLMechanism(“PLAIN”, 0);
      // Connect
      connection.connect();

      Have a look at connectToGtalk() method for reference

  2. Pingback: XMPP et Java avec Smack : b.a.-ba - 30 minutes par jour

  3. dtintruder says:

    I am getting this error

    Status :: Error Error :: null Exception :: feature-not-implemented(501)
    Is it done? true

    I attached smack source to the problem but i could not see the source for filepart.

  4. Pingback: XMPP et Java avec Smack : b.a.-ba - 30 minutes par jour

  5. SteveRob says:

    Hello! Ive been trying to build an IM client using Smack API 3.2.1 for Gtalk.

    I coded everything. But the problem is Im not able to login to the server at all.
    I get the following error:

    “SASL authentication PLAIN failed: not-authorized”

    from the authenticate method of SASLAuthentication class. I set the SASL Auth mechanism to “PLAIN” also.. Still Im not able to connect.

    Have Google changed their auth protocol or smack dont support em anymore?

  6. Vighnesh says:

    couldn’t setup local SOCKS5 proxy on port 7777: Address already in use: JVM_Bind

  7. Bill says:

    I have this code running, can log on and make a connection, and can send out a chat message that gets received by the target person. BUT! When they send me a message it never causes the processMessage handler to be invoked. I can see the incoming message packet being displayed in the Smack debug window, it looks fine, but does not reach the listener.

    I have other client code similar to this and get the same symptoms. Is there a Smack bug or do we need to add additional code now that connects the listener?

    I am using Smack 3.2.2 that I just downloaded yesterday.

  8. prasanna says:

    I am a newbie and want to build some of apps like tracing the current location of user and want to set as status,and want to find people who are online but invisible.and many more.So,plzz let me know where to start i want to build this applications in java.So,tell me some tutorials or books where to start.I have a less time so some one help me.

  9. kalpana says:

    I have try to send a file using file transfer but it is crash. Crash report is NullpointerException in FileTransferNegotiator. I don’t know where is porblem and how to solve it. so please help me. Thanks

  10. prashant says:

    Exception in thread “main” java.lang.NoClassDefFoundError: org/xmlpull/v1/XmlPullParser
    at org.jivesoftware.smack.Connection.(Connection.java:118)
    at HelloWorld.connectTOGTalk(HelloWorld.java:31)
    at HelloWorld.main(HelloWorld.java:23)
    Caused by: java.lang.ClassNotFoundException: org.xmlpull.v1.XmlPullParser
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    … 3 more

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 27 other followers

%d bloggers like this: