File transfer using Smack

Hi All,

From last one month i was trying to build my own IM client using Smack API and openfire server 3.6.3, and i got success in my effort.

right now my client is able to show me a roster list, chat and presence info and also able to deal with other gateways like MSN, Yahoo, Gtalk.

Now i m trying to go one step ahead and want to put option for file transfer, can u guys plz help me for this.?

Hi All,

My code is given below:

package com.server.wirkle.imclient;

import java.awt.;
import java.awt.event.
;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import org.jivesoftware.smack.Chat;
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.ServiceDiscoveryManager;
import org.jivesoftware.smackx.filetransfer.FileTransferListener;
import org.jivesoftware.smackx.filetransfer.FileTransferManager;
import org.jivesoftware.smackx.filetransfer.FileTransferNegotiator;
import org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Collection;

public class imClient extends JFrame implements ActionListener {

private String screenName;

// GUI stuff
private JPanel panel = new JPanel();

private JTextArea enteredText = new JTextArea(10, 32);
private JTextField typedText = new JTextField(32);
private JButton shareButton = new JButton(“share”);

private JFileChooser fileChooser ;

private Socket socket;

private OutputStream out;
private BufferedReader in;

private final String clientName;

private final String clientPassword;

private final String friendName;

public static final String SERVER_NAME = “localhost”;
public static final int SERVER_PORT = 5222;

private Chat chat;

private XMPPConnection connection;

FileTransferManager manager ;


public imClient(String clientName, String clientPassword,           String friendName) {

this.clientName = clientName;
this.clientPassword = clientPassword;
this.friendName = friendName;
XMPPConnection.DEBUG_ENABLED = true;
shareButton.addActionListener(this);
// connect to server
try {
final org.jivesoftware.smack.ConnectionConfiguration configuration = new org.jivesoftware.smack.ConnectionConfiguration(
imClient.SERVER_NAME, imClient.SERVER_PORT);
configuration
.setSecurityMode(org.jivesoftware.smack.ConnectionConfiguration.SecurityMode.di sabled);
configuration.setCompressionEnabled(false);

        this.connection = new XMPPConnection(configuration);
        this.connection.connect();
        this.connection.login(this.clientName, this.clientPassword);
   
   
       
        if (connection.isConnected())
            new MyRoster(connection.getRoster(), this.friendName);
        MessageListener listener = new SimpleMessageListner();
        chat = connection.getChatManager().createChat(this.friendName,
                listener);
    } catch (XMPPException ex) {
        ex.printStackTrace();
    }

// create GUI stuff
enteredText.setEditable(false);
enteredText.setBackground(Color.LIGHT_GRAY);
typedText.addActionListener(this);

Container content = getContentPane();
content.add(new JScrollPane(enteredText), BorderLayout.CENTER);
content.add(typedText, BorderLayout.NORTH);
content.add(shareButton, BorderLayout.SOUTH);
// display the window, with focus on typing box
setTitle(“Chat Client 1.0: [” + this.friendName + “]”);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
typedText.requestFocusInWindow();
setVisible(true);

}

// process TextField after user hits Enter
public void actionPerformed(ActionEvent e) {

    if (e.getSource() == shareButton) {
        System.out.println("share button clicked");
        fileChooser = new JFileChooser();
        int showOpenDialog = fileChooser.showOpenDialog(imClient.this);
        if(showOpenDialog == JFileChooser.APPROVE_OPTION){
            File file = fileChooser.getSelectedFile();
            System.out.println(file.getName()+" is selected for sharing");
           
            this.manager = new FileTransferManager(this.connection);
            OutgoingFileTransfer outgoingFileTransfer = manager.createOutgoingFileTransfer("wirkle@jabber.prabhat");
            try {
                outgoingFileTransfer.sendFile(file, "testing");
            } catch (XMPPException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            //FileTransferNegotiator negotiator = new FileTransferNegotiator();
            System.out.println("is file transfer negotiatiated  "+FileTransferNegotiator.isServiceEnabled(this.connection));
           
            //this.manager.createOutgoingFileTransfer(friendName);
           
        }
    } else {
        Message message = new Message();
        message.setBody(typedText.getText());
        try {
            chat.sendMessage(message);
        } catch (XMPPException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        // System.out.println("[" + screenName + "]: " +
        // typedText.getText());
        typedText.setText("");
        typedText.requestFocusInWindow();

}
}

public static void main(String[] args) {
imClient client = new imClient("", “”,
"");
// client.listen();
}

private class SimpleMessageListner implements MessageListener {
    public void processMessage(Chat chat, Message message) {
        String reply = message.getBody();
        if (reply != null)
            enteredText.append("\n " + message.getBody());
        // System.out.println("Received message: " + message.getBody());
    }
}

}

class MyRoster extends JFrame implements ActionListener {

public MyRoster(Roster roster, String friendName) {

JPanel panel = new JPanel();
this.getContentPane().add(panel);
JTextArea textArea = new JTextArea();
panel.add(textArea);
this.setVisible(true);
this.setSize(100, 500);
Roster.setDefaultSubscriptionMode(Roster.SubscriptionMode.accept_all);
try {
roster.createEntry(friendName, “”, null);
} catch (XMPPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

// this.presenceStatus(roster, “”);
// this.presenceStatus(roster, friendName);

final Collection entries = roster.getEntries();
for (RosterEntry entry : entries) {
textArea.append("\n " + entry);
}

}

public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub

}

}

As long as i m do chat , above code works fine but when i selects ay file it throws below exception.

Exception in thread “AWT-EventQueue-0” java.lang.NullPointerException
at org.jivesoftware.smackx.filetransfer.FileTransferNegotiator.setServiceEnabled(F ileTransferNegotiator.java:126)
at org.jivesoftware.smackx.filetransfer.FileTransferNegotiator.getInstanceFor(File TransferNegotiator.java:107)
at org.jivesoftware.smackx.filetransfer.FileTransferManager.(FileTransferMan ager.java:64)
at com.server.wirkle.imclient.imClient.actionPerformed(imClient.java:143)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

Any idea ?

Thanks in advance.

if you look at the last error, you notice that it is a NullPointerException

Exception in thread “AWT-EventQueue-0” java.lang.NullPointerException
at org.jivesoftware.smackx.filetransfer.FileTransferNegotiator.setServiceEnabled(F ileTransferNegotiator.java:126)

so if you trace it all the way to the F ileTransferNegotiator line 126 , you will notice that “manager” in the following line is null

manager.addFeature(ns);

and the manager get its instance at the start of the method as follow:

ServiceDiscoveryManager manager = ServiceDiscoveryManager
.getInstanceFor(connection);

It is assumed that ServiceDiscoveryManager is already initiated and getting back the instance of it. I don’t know the important nor innerworking of the ServiceDiscoveryManager. However you can solve that error by initiating ServiceDiscoveryManager before you initiate FileTransferManager as follow

ServiceDiscoveryManager sm=new ServiceDiscoveryManager(connection);
FileTransferManager manager = new FileTransferManager(connection);

Hope you will come back and give me point for this answer

win

1 Like

Absolutely correct solution.

It works fine.

Thank you.

Hi there!!

I am using file transfer right now. I do receive files properly but problems come when I try to send a file. When I do send a file, a pop up appears in the Pidgin client of Psi client. I accept the file but the transfere never starts. What I am doing wrong??

I have tryed to look it un in the forum but found no answer. Thanks in advance for your help!!

there are often problems sending files between different clients. the most common problem is that one or even both of the clients didn’t implement the xmpp protocol extension (XEP-0096 for file transfer) very well, so they use different xml tags to negotiate a file transfer, for example.

start transfering files only in your local network befor you try to send files through NATs/firewalls. maybe you could use the smack debugger to have a look at the packages the clients are sending to each other.

Thanks for your answer!!!

I am still having this problem. The invitation to receive the message arrives to the client (e.g. Pidgin) and I accept it, but the transfer never really starts. When printing the status it Negotiates the transfer but then when negotiating the stream it stops.

The transfer.getException() is returning “feature-not-implemented(501)”.

I have used the debugger as you suggested, and this is what I have seen:

Just before receiving the message with the error DiscoverItems is sending this:

And the error message is this one:

Any idea?? If you wish I could show the previous messages. Thanks!!