tags:

views:

76

answers:

3

I have two classes that should be communicating but they aren't. One is called Chatter and when a listener receives a message within Chatter it should call a method within the second class which is called ClassView. But I don't think the method is being called.

Here is the code for Chatter:

package instantmessengerplugin;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.TableItem;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.filter.MessageTypeFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;

public class Chatter {

    public XMPPConnection connection;
    public String user;
    public ClassView classView;
    public Chat chat;
    public PacketFilter packetFilter;
    public PacketListener listener;




    public Chatter(XMPPConnection connection1,String user1, Display dist)
    {
        connection  = connection1;
        user = user1;

        openChat();
        classView = new ClassView(dist,chat);
    }

    public void  openChat()
    {
        ChatManager cm = connection.getChatManager();
        chat = cm.createChat(user, new MessageListener()
        {
            public void processMessage(Chat chat ,Message message)
            {
                if(message.getType().equals(Message.Type.chat))
                {
                    //TableItem item = new TableItem(classView.chatViewer,SWT.NONE);
                    //item.setText("Them: " + message.getBody());
                    System.out.println(message.getBody());
                    classView.updateChat(message);
                }


            }
        }




        );


    }





}

And here is the code for ClassView:

package instantmessengerplugin;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;


public class ClassView {

    public Display displayChat;
    public Shell shellChat;
    final Table chatViewer;
    public Chat chat;

    public ClassView(Display dist,Chat chat1){

        chat = chat1;

        displayChat = dist;
        shellChat = new Shell(displayChat);
        GridLayout gridLayout = new GridLayout();
        gridLayout.numColumns = 2;
        shellChat.setLayout(gridLayout);

        Label contact = new Label(shellChat,SWT.NONE);
        GridData data = new GridData();
        data.horizontalAlignment = GridData.FILL;
        data.horizontalSpan = 2;
        data.grabExcessHorizontalSpace = true;
        data.grabExcessVerticalSpace = true;

        chatViewer = new Table(shellChat,SWT.NONE); 
        data = new GridData();
        data.horizontalSpan = 2;
        data.horizontalAlignment = GridData.FILL;
        data.verticalAlignment = GridData.FILL;
        data.grabExcessHorizontalSpace = true;
        chatViewer.setLayoutData(data);

        final Text chatBox = new Text(shellChat,SWT.SINGLE);
        data = new GridData();
        data.verticalAlignment = GridData.FILL;
        data.horizontalAlignment = GridData.FILL;
        data.grabExcessHorizontalSpace = true;
        chatBox.setLayoutData(data);

        Button send = new Button(shellChat,SWT.PUSH);
        send.setText("Send");

        send.addSelectionListener(new SelectionAdapter(){

            public void widgetSelected(SelectionEvent e)
            {

                String s = chatBox.getText();
                TableItem item = new TableItem(chatViewer, SWT.NONE);
                item.setText("Me: " + s);
                try {
                    chat.sendMessage(s);
                } catch (Exception e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }

                chatBox.setText("");
            }

        });










        shellChat.pack();
        shellChat.open();

        while(!shellChat.isDisposed())
        {
            if(!displayChat.readAndDispatch())
            {
                displayChat.sleep();
            }
        } 



    }


    public void updateChat(Message message)
    {
        TableItem item = new TableItem(chatViewer,SWT.NONE);
        item.setText("Them: " + message.getBody());
    }



}

When the processMessage method in Chatter is called it should speak to ClassView which will call updateChat which then changes the table object in ClassView. It doesn't seem to be happening. The table isn't changed and there isn't an exception thrown. I know that chatter is working correctly because it prints the message to the console just fine.

Does anyone know why updateChat doesn't seem to be getting called?

Update:

I have ran the debugger at the code in question. Here is the debug stack of what is being called at execution:

FutureTask$Sync.innerRun() line: not available [local variables unavailable]

FutureTask.run() line: not available
ThreadPoolExecutor$Worker.runTask(Runnable) line: not available
ThreadPoolExecutor$Worker.run() line: not available
Thread.run() line: not available [local variables unavailable]

I am not sure what it means exactly. Mention of threads is what made me think it was something to do the method call not being synchronised with another thread.

A: 

This is speculation, but it appears your updateChat message just creates a TableItem without adding it to any table.

    public void updateChat(Message message)
{
    TableItem item = new TableItem(chatViewer,SWT.NONE);
    item.setText("Them: " + message.getBody());
}
emory
The `chatViewer` is the table object. The table item is created 'on' that table which includes adding the item to the table. But the table may have to be refreshed (there is a `refresh` method somewhere, maybe on `chatViewer`, maybe on its parent)
Andreas_D
A: 

You should debug the code with eclipse (guess you use this IDE as you use SWT). Set a breakpoint inside processMessage and step through the code. Then you'll see if updateChat is called or not.

Andreas_D
I used the debugger like you said. It turns out the updateChat wasn't getting called. However if you call updateChat from within it's own class it works fine. I think the code in the Chatter class will have to be synced with the UI thread in the ClassView class. But I'm not sure how to do this. Is it the syncExec method?
Joshy910
But then - what *is* being called at line `classView.updateChat(message);`, the program must continue somewhere, and you said, the previous line *gets* executed.
Andreas_D
I have updated the question with details of what is being called at classView.updateChat(message).
Joshy910
A: 

I had a similar bug with Smack, in my case the trick was that the real bug was a NullPointer exception. Here is my code:

for(PartnerMessageCallback callback : callbacks) {
   callback.processMessage(null, message);
}

A NullPointer exception has thrown from the processMessage, but I see the following in the StackTrace:

FutureTask$Sync.innerRun() line: not available [local variables unavailable]

In my case, a simple try-catch solved the problem:

for(PartnerMessageCallback callback : callbacks) {
  try {
    callback.processMessage(null, message);
  } catch (Exception ex) {
    ex.printStackTrace();
  }
}

I hope it helps you.

Faz