0

i'm writing a program that connects with various TCP network devices. The GUI is made using JavaFX. The whole connection part is in its own package "Network". Roughly described, it looks like this: (I don't know much about UML, no blaming plaese :/ - i just needed a way to quickly describe how my program structure looks). https://i.stack.imgur.com/PSdsH.jpg

okay thats how it is: The TCP classes are stored in a synchronized List in "NetworkManager". These classes hold information about the connection (how much data received yet, ip, mac etc.). The Rcv-Thread constantly tries to receive data.

well, this is what i want: As soon as the Rcv-Thread receives a specific message, the controller should be invoked to do something (GUI refresh or whatever). Also the controller should stay decoupled from the "Network" module-> it is reused in another project. I want to achieve this behaviour through an custom event. In short: TCP-Rcv-Thread needs to be able to give information to the Controller. But i dont really know how to get it all to work. Lets see where i am:

  • I have an event class in the "Network" module.

    import java.util.EventObject;
    
    public class XEvent extends EventObject{
      String message;
        public XEvent(Object source, String message) {
        super(source);
        this.message = message;
      }
    
    public String getMessage() {
        return message;
     }
    }  
    
  • I have a listener class in the "Network" module.

     import java.util.EventListener;
        public interface XListener extends EventListener{
        void handlerMethod1(XEvent event);
        void handlerMethod2(XEvent event);
    }
    
  • I tried to prepare my Rcv-Thread for firing the event:

    import javax.swing.event.EventListenerList;
    import java.io.IOException;
    
    public class ReceiveDataThread implements Runnable {
    protected EventListenerList listenerList = new EventListenerList();
    }
    
    protected void addXListener(XListener xListener) {
            listenerList.add(XListener.class, xListener);
        }
    
    
    
    protected void removeListener(XListener xListener) {
            listenerList.remove(XListener.class, xListener);
        }
    
    protected void fireHandlerMethod1(String message) {
        XEvent event = null;
        Object[] list = listenerList.getListenerList();
        for (int i = 0; i < list.length; i += 2) {
            if (list[i] == XListener.class) {
                if (event == null) event = new XEvent(this, message);
                XListener l = (XListener) list[i + 1];
                l.handlerMethod1(event);
            }
        }
    }
    
    protected void fireHandlerMethod2(String message) {
        XEvent event = null;
        Object[] list = listenerList.getListenerList();
        for (int i = 0; i < list.length; i += 2) {
            if (list[i] == XListener.class) {
                if (event == null) event = new XEvent(this, message);
                XListener l = (XListener) list[i + 1];
                l.handlerMethod2(event);
            }
        }
    }
    
    @Override
    public void run() {
        String s;
        while (!stopThread) {
            s = receiveData();
            System.out.println("test");
            fireHandlerMethod1(s);
        }
    }
    
  • The Controller (this class should react on the custom events) implements the Listener:

    public class Controller implements Initializable, XListener {
    @Override
    public void handlerMethod1(XEvent event) {
        System.out.println("Event1: " + event.getMessage());
    }
    
    @Override
    public void handlerMethod2(XEvent event) {
    
     }
    }
    

And from there on i'm not really shure how to get it work that my events (fired from my Rcv-Thread) are noticed by my controller class. I think i have to add a listener to every Rcv-Thread object via the controller class (just like when i use a ButtonListener, ...) . The problem is: from my TCP Class i can't access the Rcv-Thread-object's addXListener method - even when set to public (but i can access the Rcv-Thread-Classes from the list). I tried to read as much as i can about the problem but cant figure out how to get this to work. What am i missing?

edit1: TCP class:

public class TCPClass{
private Thread receiveDataThread;
private String MAC;     
private InetAddress IP;
private Socket socket = new Socket();  
private int tcpSendPort;
private int timeOut = 10;    
private ObjectOutputStream objectOutputStream;
private BufferedReader bufferedReader;
private String connectionStatus = "offline";  


public TCPClass(DatagramPacket datagramPacket) {
    IP = datagramPacket.getAddress();
    setConnectionStatusOnline();
    tcpSendPort = 50000 + NetworkManager.getNumberOfConnections();
    MAC = extractMac(datagramPacket);
}
    public void connect(int tcpPort) {
    try {
        socket = new Socket(IP, tcpPort, null, tcpSendPort);
        bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        receiveDataThread = new Thread(new ReceiveDataThread(this));
        receiveDataThread.start();
        InputStreamReader(socket.getInputStream()));
    } catch (IOException e) {
        e.printStackTrace();
        System.out.println("on MAC: " + getMAC() + "\non Device:" + toString());
    }
    if (socket.isConnected()) {
        setConnectionStatusConnected();
    }
}
}

The NetworkManager creates an object of TCPClass and calls the connect() method.

JohnSmith
  • 33
  • 6
  • are you using normal java serialization or you're literally implementing TCP protocols and sending it over the network? – Breno Inojosa Sep 12 '14 at 06:15
  • I use the standard Java Socket -> Socket(IP. tcpPort, null, tcpSendPort), and receive data via bufferedReader.read(), so i'm not building my own TCP protocol, if that is what you meant – JohnSmith Sep 12 '14 at 06:19
  • so ok, you're serializing :P can you edit the topic and post your TCP Class? (or an implementation of one) – Breno Inojosa Sep 12 '14 at 06:19
  • I was writing an answer, but..you realize A is not coupled to B if B is the one that makes all the calls, right? In other terms, as long as your Controller is only called and doesn't call or accepts specific parameters from classes from your network module, it's all good. – Breno Inojosa Sep 12 '14 at 06:34
  • i might not get this right, but i wrote in my question, i need to pass information from my rcv-thread to controller. But i don't want to call my controller because the NetworkManager class might not be an object of an Controller (thats the case if NetworkManager is reused in another project). So i need a way to decouple this - and an custom event seems to be good for this case – JohnSmith Sep 12 '14 at 06:46

1 Answers1

0

Ok so after days i figured it out myself. The main problem was that i was not able to call the addXListener() method of Rcv-Thread from the Controller. I took the Custom Event stuff out of the Rcv-Thread and moved it to the TCP-Class. Now i'm able to add the Listener to these classes. If i want to fire an event from the Rcv-Thread i simply call fireHandlerMethod() from its superclass (TCP-Class) - and everything works as expected.

JohnSmith
  • 33
  • 6