From e66dba88125e0c3de259f6ee98b39fde97d750f2 Mon Sep 17 00:00:00 2001 From: kske Date: Mon, 30 Dec 2019 18:18:03 +0200 Subject: [PATCH] Receiving objects from server on separate thread --- src/main/java/envoy/client/Client.java | 38 ++++++++------ .../java/envoy/client/ObjectProcessor.java | 15 ++++++ src/main/java/envoy/client/Receiver.java | 50 +++++++++++++++++++ src/main/java/envoy/client/ui/Startup.java | 1 + 4 files changed, 88 insertions(+), 16 deletions(-) create mode 100644 src/main/java/envoy/client/ObjectProcessor.java create mode 100644 src/main/java/envoy/client/Receiver.java diff --git a/src/main/java/envoy/client/Client.java b/src/main/java/envoy/client/Client.java index 6a4b754..a037e8c 100644 --- a/src/main/java/envoy/client/Client.java +++ b/src/main/java/envoy/client/Client.java @@ -1,7 +1,5 @@ package envoy.client; -import java.io.IOException; -import java.io.InputStream; import java.net.Socket; import java.util.Map; import java.util.logging.Logger; @@ -9,6 +7,7 @@ import java.util.logging.Logger; import envoy.client.util.EnvoyLog; import envoy.data.LoginCredentials; import envoy.data.User; +import envoy.exception.EnvoyException; import envoy.util.SerializationUtils; /** @@ -23,10 +22,11 @@ import envoy.util.SerializationUtils; */ public class Client { - private Socket socket; - private Config config = Config.getInstance(); - private User sender, recipient; - private boolean online; + private Socket socket; + private Config config = Config.getInstance(); + private volatile User sender; + private User recipient; + private boolean online; private static final Logger logger = EnvoyLog.getLogger(Client.class.getSimpleName()); @@ -34,11 +34,11 @@ public class Client { * Enters the online mode by acquiring a user ID from the server. * * @param credentials the login credentials of the user - * @throws IOException if the online mode could not be entered or the request - * failed for some other reason + * @throws Exception if the online mode could not be entered or the request + * failed for some other reason * @since Envoy v0.2-alpha */ - public void onlineInit(LoginCredentials credentials) throws IOException { + public void onlineInit(LoginCredentials credentials) throws Exception { logger.info(String.format("Attempting connection to server %s:%d...", config.getServer(), config.getPort())); socket = new Socket(config.getServer(), config.getPort()); logger.info("Successfully connected to server."); @@ -47,14 +47,20 @@ public class Client { logger.finest("Sending login credentials..."); SerializationUtils.writeBytesWithLength(credentials, socket.getOutputStream()); - // Read response (user object) - InputStream in = socket.getInputStream(); + // Create message receiver + Receiver receiver = new Receiver(socket.getInputStream()); - // Read object - try { - sender = SerializationUtils.read(in, User.class); - } catch (ClassNotFoundException e) { - throw new IOException(e); + // Register user creation processor + receiver.registerProcessor(User.class, sender -> { logger.info("Acquired user object " + sender); this.sender = sender; }); + + // Start receiver + new Thread(receiver).start(); + + // Wait for a maximum of five seconds to acquire the sender object + long start = System.currentTimeMillis(); + while (sender == null) { + if (System.currentTimeMillis() - start > 5000) throw new EnvoyException("Did not log in after 5 seconds"); + Thread.sleep(500); } online = true; diff --git a/src/main/java/envoy/client/ObjectProcessor.java b/src/main/java/envoy/client/ObjectProcessor.java new file mode 100644 index 0000000..b0aed2d --- /dev/null +++ b/src/main/java/envoy/client/ObjectProcessor.java @@ -0,0 +1,15 @@ +package envoy.client; + + +/** + * Project: envoy-client
+ * File: ObjectProcessor.java
+ * Created: 30.12.2019
+ * + * @author Kai S. K. Engelbart + * @since Envoy v0.3-alpha + */ +public interface ObjectProcessor { + + void process(T input); +} \ No newline at end of file diff --git a/src/main/java/envoy/client/Receiver.java b/src/main/java/envoy/client/Receiver.java new file mode 100644 index 0000000..64a4655 --- /dev/null +++ b/src/main/java/envoy/client/Receiver.java @@ -0,0 +1,50 @@ +package envoy.client; + +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import envoy.client.util.EnvoyLog; + +/** + * Project: envoy-client
+ * File: Receiver.java
+ * Created: 30.12.2019
+ * + * @author Kai S. K. Engelbart + * @since Envoy v0.3-alpha + */ +public class Receiver implements Runnable { + + private InputStream in; + private Map, ObjectProcessor> processors = new HashMap<>(); + + private static final Logger logger = EnvoyLog.getLogger(Receiver.class.getSimpleName()); + + public Receiver(InputStream in) { this.in = in; } + + @SuppressWarnings("unchecked") + @Override + public void run() { + try (ObjectInputStream oin = new ObjectInputStream(in)) { + while (true) { + Object obj = oin.readObject(); + logger.finest("Received object " + obj); + + // Get appropriate processor + ObjectProcessor processor = processors.get(obj.getClass()); + if (processor == null) + logger.severe(String.format("The received object has the class %s for which no processor is defined.", obj.getClass())); + else + processor.process(obj); + } + } catch(Exception e) { + logger.log(Level.SEVERE, "Error on receiver thread", e); + } + } + + public void registerProcessor(Class processorClass, ObjectProcessor processor) { processors.put(processorClass, processor); } +} \ No newline at end of file diff --git a/src/main/java/envoy/client/ui/Startup.java b/src/main/java/envoy/client/ui/Startup.java index 2faaa1a..1a2c96e 100644 --- a/src/main/java/envoy/client/ui/Startup.java +++ b/src/main/java/envoy/client/ui/Startup.java @@ -101,6 +101,7 @@ public class Startup { client.onlineInit(new LoginCredentials(userName, pass.toCharArray())); } catch (Exception e1) { logger.warning("Could not connect to server. Trying offline mode..."); + e1.printStackTrace(); try { // Try entering offline mode localDB.loadUsers();