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.