I am working on 2 applications (web and standalone apps). I have built functionality into the web app for users to be able to restart certain modules of the standalone app from the web page. The way i accomplish this is using a ServerSocket object that listens on a port that is configured as a parameter in the database. This is a shortened version of the server side that listens for the incoming requests :
try
{
int port = Integer.parseInt(globalParamService.findByName("serviceInterconnectPort").getValue());
ServerSocket serverSocket = new ServerSocket(port);
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Successfully started web client connector on port " + port);
while(running)
{
socket = serverSocket.accept();
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Incoming request from web client");
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
if (message.contains("Restart Web Client Connector"))
{
if (!main.isWebClientConnectorRestarting())
{
main.restartWebClientConnector();
String returnMessage = "Done\n";
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage);
bw.flush();
os.close();
osw.close();
bw.close();
}
else
{
String returnMessage = "Request cancelled\n";
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage);
bw.flush();
os.close();
osw.close();
bw.close();
logEntryService.logWarning(LogEntry.CONNECTIVITY, "Web client connector restart request cancelled, restart already in progress");
}
}
is.close();
isr.close();
br.close();
socket.close();
}
}
catch (Exception ex)
{
logEntryService.logError(LogEntry.CONNECTIVITY, "Error processing restart request from web client : " + ex.getMessage());
}
Upon deployment of my 2 apps, it is possible that the users would need to change the port this listener is running on. When they do change it from the web app, i extract the unchanged port before updating it in the DB and send it to the below method :
public void restartWebClientConnector(int oldPort)
{
Thread t = new Thread(() ->
{
try
{
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Connecting to port " + oldPort + " to restart web client connector");
InetAddress address = InetAddress.getByName("localhost");
socket = new Socket(address, oldPort);
logEntryService.logDebug(LogEntry.CONNECTIVITY, "Successfully connected to port " + oldPort);
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write("Restart Web Client Connector\n");
bw.flush();
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
if (message.compareTo("Done") == 0)
{
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Web client connector restart request acknowledged");
}
else
{
logEntryService.logWarning(LogEntry.CONNECTIVITY, "Web client connector restart request cancelled, restart already in progress");
}
os.close();
osw.close();
bw.close();
is.close();
isr.close();
br.close();
socket.close();
}
catch (IOException | NumberFormatException ex)
{
logEntryService.logError(LogEntry.CONNECTIVITY, "Error sending web client connector restart command : " + ex.getMessage());
}
});
t.start();
}
This method then calls the following code which terminates my listener thread and re initializes it on the new updated port number :
public void restartWebClientConnector()
{
if (!webClientConnectorRestarting)
{
webClientConnectorRestarting = true;
webClientConnector.setRunning(false);
webClientConnectorThread.interrupt();
initWebClientConnector();
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Successfully restarted web client connector");
webClientConnectorRestarting = false;
}
}
private void initWebClientConnector()
{
logEntryService.logInfo(LogEntry.CORE, "Initializing web connector");
try
{
webClientConnector = new WebClientConnector(this, globalParamService, logEntryService);
webClientConnectorThread = new Thread(threads, webClientConnector);
webClientConnectorThread.setName("Web Client Connector Thread");
webClientConnectorThread.start();
}
catch (Exception ex)
{
logEntryService.logError(LogEntry.CORE, "Error initializing messaging process : " + ex.getMessage());
}
}
Everything works great except one thing : the old port number is NOT freed up despite explicitly closing everything i can think of. When doing netstat -a after changing the port from the web client, the old port is still listed in LISTENING status. I can change it several times in a row and it works every time but the ports are not freed up. I have spent quite some time researching this and from what i've read it appears i am doing everything correctly (evidently not!).
Whatever input you guys may have would be helpful.
Cheers!