I'm really confused by this: some of my code is not working when i run my program normally in eclipse, but it does wok when i run through each step separately using the debug mode.
Code:
public void showConnectDialog() {
ConnectDialog connectDialog = new ConnectDialog();
connectDialog.setVisible(true);
//Until here, code runs
while(! connectDialog.getConnected()) {};
//The next line does only run in debug
JOptionPane.showMessageDialog(connectDialog, "Connected", "Connected", JOptionPane.INFORMATION_MESSAGE);
}
The connector (is started (as a thread) as soon as the user hits 'connect' in the dialog):
private class ServerConnector implements ActionListener, Runnable {
@Override
public void actionPerformed(ActionEvent e) {
if (! IP_field.getText().equals("")) {
if (! isConnecting) {
new Thread(new ServerConnector(), "ServerConnector").start();
}
}
else {
JOptionPane.showMessageDialog(dialog,
"Enter an IP address",
"Enter IP",
JOptionPane.WARNING_MESSAGE);
}
}
@Override
public void run() {
try {
setConnecting(true);
Socket socket = connect();
if (socket != null) {
ObjectOutputStream oOut = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream oIn = new ObjectInputStream(socket.getInputStream());
if (login(oOut, oIn)) {
isConnected = true;
setConnecting(false);
}
else {
socket.close();
}
setConnecting(false);
}
}
catch (RSPException e) {
e.printStackTrace();
System.exit(1);
}
catch (Exception e) {
//If an exception occurs, setConnecting() will be true. This
//not good, so it has to be set to false
e.printStackTrace();
setConnecting(false);
}
}
private boolean login(ObjectOutputStream oOut, ObjectInputStream oIn)
throws ClassNotFoundException, IOException, RSPException {
//Send login request action:
oOut.writeObject(new LoginAction(ActionSender.CLIENT, getID(),
getPassword()));
Object obj = oIn.readObject();
if (obj instanceof LoginActionResult) {
LoginActionResult result = (LoginActionResult) obj;
if (result.getResult() == LoginResults.SUCCES) {
return true;
}
else if (result.getResult() == LoginResults.FAIL_ON_ID) {
JOptionPane.showMessageDialog(dialog,
"Invalid password or ID",
"Can't login",
JOptionPane.ERROR_MESSAGE);
return false;
}
else if (result.getResult() == LoginResults.FAIL_ON_PASSWORD) {
JOptionPane.showMessageDialog(dialog,
"Invalid password or ID",
"Can't login",
JOptionPane.ERROR_MESSAGE);
return false;
}
else if (result.getResult() == LoginResults.SERVER_FULL) {
JOptionPane.showMessageDialog(dialog,
"Couldn't connect: \n" +
"Server is full",
"Failed to connect",
JOptionPane.WARNING_MESSAGE);
return false;
}
else {
return false;
}
}
else {
System.out.println(obj);
throw new RSPException("Server is not following the protocol.");
}
}
private void setConnecting(boolean connecting) {
if (connecting) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
connectButton.setEnabled(false);
}
});
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
connectButton.setText("Connecting...");
}
});
}
else {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
connectButton.setText("Connect");
}
});
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
connectButton.setEnabled(true);
}
});
}
isConnecting = connecting;
}
private String getAddressFromTextField() {
return IP_field.getText();
}
private InetAddress getInetAddress(String fullAddress) {
try {
if (fullAddress.contains(":")) {
String[] splitAddress = fullAddress.split(":");
return InetAddress.getByName(splitAddress[0]);
}
else {
return InetAddress.getByName(fullAddress);
}
}
catch (UnknownHostException e) {
return null;
}
}
private int getPort(String fullAddress) {
try {
String[] splittedAddress = fullAddress.split(":");
return Integer.valueOf(splittedAddress[1]);
}
catch (NumberFormatException ex) {
return -1;
}
catch (NullPointerException
| ArrayIndexOutOfBoundsException
| PatternSyntaxException ex) {
//Returning default port value: 25566, because no port was given
return 25566;
}
}
@SuppressWarnings("resource")
private Socket connect() {
Socket socket = null;
InetAddress address = null;
if ((address = getInetAddress(getAddressFromTextField())) == null) {
return null;
}
int port = getPort(getAddressFromTextField());
try {
socket = new Socket(address, port);
}
catch (ConnectException e ) {
Socket retrySocket = null;
if ((retrySocket = retryConnect(address, port)) == null) {
JOptionPane.showMessageDialog(dialog,
"Connection timed out",
"Failed to connect",
JOptionPane.ERROR_MESSAGE);
setConnecting(false);
}
else {
socket = retrySocket;
}
}
catch(IOException e) {
e.printStackTrace();
}
return socket;
}
private Socket retryConnect(InetAddress address, int port) {
Thread waitThread = new Thread(new Runnable() {
@Override
public void run() {
try {
//Will wait 15(000) (milli)seconds before stopping with
//trying to connect.
//One second (1000 millis) is for debugging and testing
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
});
waitThread.start();
while (waitThread.isAlive()) {
try {
return new Socket(address, port);
}
catch (ConnectException e) {
//Do nothing, will re-attempt to connect.
}
catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
private String getID() {
return ID_field.getText();
}
private String getPassword() {
if (getID().equals("master")) {
return "masterPassword";
}
else {
return new String(passwordField.getPassword());
}
}
}
getConnected() returns true as soon as it's connected to the server. The connector is running on a separate thread.
EDIT: I tried to put code in the getConnected() while block, and then it works. Why does it works then and not else?
ConnectDialog?waitandnotifyhere. TheshowConnectDialogwaits until theServerConnectorthread notifies it. That way you can avoid thewhileloop and your program won't block a cpu core.isConnectingvariable is defined... is it defined asvolatile? docs.oracle.com/javase/tutorial/essential/concurrency/…