Feat: Keep startup LOGIN connection and expose shared ClientService
Introduce ClientApp.sharedClientService, create it on startup when a username is provided, run the startup LOGIN asynchronously on that connection and keep the socket open so the UI reuses it; add Javadoc and adjust logging.
This commit is contained in:
@@ -1,26 +1,44 @@
|
|||||||
package ch.unibas.dmi.dbis.cs108.casono.client;
|
package ch.unibas.dmi.dbis.cs108.casono.client;
|
||||||
|
|
||||||
/**
|
import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService;
|
||||||
* Entry point for the Casono client application. Handles client startup and connection parameters.
|
import ch.unibas.dmi.dbis.cs108.casono.client.network.LobbyClient;
|
||||||
*/
|
import ch.unibas.dmi.dbis.cs108.casono.client.network.LoginResult;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.ui.Launcher;
|
import ch.unibas.dmi.dbis.cs108.casono.client.ui.Launcher;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry point for the Casono client application. Handles client startup and connection parameters.
|
* Entry point and bootstrap helper for the Casono client application.
|
||||||
*
|
*
|
||||||
* <p>Default constructor for the application.
|
* <p>This class is responsible for two tasks: - performing an optional startup LOGIN when a
|
||||||
|
* username is supplied on the command line, and - providing a shared {@link ClientService} instance
|
||||||
|
* that the UI can reuse so the initial connection remains active.
|
||||||
*/
|
*/
|
||||||
public class ClientApp {
|
public class ClientApp {
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(ClientApp.class);
|
private static final Logger LOGGER = LogManager.getLogger(ClientApp.class);
|
||||||
|
|
||||||
|
/** Shared client connection used when a username is provided at startup. */
|
||||||
|
private static volatile ClientService sharedClientService;
|
||||||
|
|
||||||
/** Default constructor. */
|
/** Default constructor. */
|
||||||
public ClientApp() {
|
public ClientApp() {
|
||||||
// Default constructor
|
// Default constructor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the shared {@link ClientService} instance created during startup, or {@code null} if
|
||||||
|
* none exists. The UI may call this to reuse the connection that already performed the initial
|
||||||
|
* LOGIN.
|
||||||
|
*/
|
||||||
|
public static ClientService getSharedClientService() {
|
||||||
|
return sharedClientService;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setSharedClientService(ClientService cs) {
|
||||||
|
sharedClientService = cs;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the client application with the given address.
|
* Starts the client application with the given address.
|
||||||
*
|
*
|
||||||
@@ -36,12 +54,69 @@ public class ClientApp {
|
|||||||
int port = Integer.parseInt(parts[1]);
|
int port = Integer.parseInt(parts[1]);
|
||||||
|
|
||||||
LOGGER.info("You've selected the client. It will connect port {} at host {}", port, host);
|
LOGGER.info("You've selected the client. It will connect port {} at host {}", port, host);
|
||||||
// Pass connection defaults and optional username to the UI via system properties
|
|
||||||
System.setProperty("casono.server.host", host);
|
System.setProperty("casono.server.host", host);
|
||||||
System.setProperty("casono.server.port", String.valueOf(port));
|
System.setProperty("casono.server.port", String.valueOf(port));
|
||||||
|
// If a username was provided, create a shared connection and perform
|
||||||
|
// the initial LOGIN asynchronously on that connection. The connection
|
||||||
|
// is intentionally NOT closed so the UI can reuse it.
|
||||||
if (username != null && !username.isBlank()) {
|
if (username != null && !username.isBlank()) {
|
||||||
System.setProperty("casono.username", username);
|
try {
|
||||||
|
ClientService clientService = new ClientService(host, port);
|
||||||
|
setSharedClientService(clientService);
|
||||||
|
|
||||||
|
java.util.concurrent.ExecutorService bg =
|
||||||
|
java.util.concurrent.Executors.newSingleThreadExecutor(
|
||||||
|
r -> {
|
||||||
|
Thread t = new Thread(r);
|
||||||
|
t.setDaemon(true);
|
||||||
|
t.setName("casono-startup-login");
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
bg.submit(
|
||||||
|
() -> {
|
||||||
|
try {
|
||||||
|
LobbyClient lobbyClient = new LobbyClient(clientService);
|
||||||
|
LoginResult res = lobbyClient.login(username);
|
||||||
|
LOGGER.info(
|
||||||
|
"Assigned username='{}' id={}",
|
||||||
|
res.getUsername(),
|
||||||
|
res.getId());
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
LOGGER.warn("Startup login failed: {}", e.getMessage());
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.warn("Unexpected error during startup login", e);
|
||||||
|
} finally {
|
||||||
|
bg.shutdown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
LOGGER.warn(
|
||||||
|
"Could not establish initial connection for startup login: {}",
|
||||||
|
e.getMessage());
|
||||||
|
// UI will create its own connection when it initializes
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Launcher.main(new String[] {});
|
|
||||||
|
if (username != null && !username.isBlank()) {
|
||||||
|
Launcher.main(new String[] {arg, username});
|
||||||
|
} else {
|
||||||
|
Launcher.main(new String[] {arg});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main entry point. Usage: <host:port> [username]
|
||||||
|
*
|
||||||
|
* <p>If a username is provided the application attempts a startup LOGIN on the shared
|
||||||
|
* connection; the UI will still start and will reuse the connection when possible. The username
|
||||||
|
* is not propagated via a system property for UI display.
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
if (args == null || args.length == 0) {
|
||||||
|
throw new IllegalArgumentException("Address argument required: <host:port>");
|
||||||
|
}
|
||||||
|
// Optional username argument
|
||||||
|
String username = args.length > 1 && args[1] != null && !args[1].isBlank() ? args[1] : null;
|
||||||
|
start(args[0], username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user