Receiving objects from server on separate thread
This commit is contained in:
		| @@ -1,7 +1,5 @@ | |||||||
| package envoy.client; | package envoy.client; | ||||||
|  |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.io.InputStream; |  | ||||||
| import java.net.Socket; | import java.net.Socket; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.logging.Logger; | import java.util.logging.Logger; | ||||||
| @@ -9,6 +7,7 @@ import java.util.logging.Logger; | |||||||
| import envoy.client.util.EnvoyLog; | import envoy.client.util.EnvoyLog; | ||||||
| import envoy.data.LoginCredentials; | import envoy.data.LoginCredentials; | ||||||
| import envoy.data.User; | import envoy.data.User; | ||||||
|  | import envoy.exception.EnvoyException; | ||||||
| import envoy.util.SerializationUtils; | import envoy.util.SerializationUtils; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -23,10 +22,11 @@ import envoy.util.SerializationUtils; | |||||||
|  */ |  */ | ||||||
| public class Client { | public class Client { | ||||||
|  |  | ||||||
| 	private Socket	socket; | 	private Socket			socket; | ||||||
| 	private Config	config	= Config.getInstance(); | 	private Config			config	= Config.getInstance(); | ||||||
| 	private User	sender, recipient; | 	private volatile User	sender; | ||||||
| 	private boolean	online; | 	private User			recipient; | ||||||
|  | 	private boolean			online; | ||||||
|  |  | ||||||
| 	private static final Logger logger = EnvoyLog.getLogger(Client.class.getSimpleName()); | 	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. | 	 * Enters the online mode by acquiring a user ID from the server. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param credentials the login credentials of the user | 	 * @param credentials the login credentials of the user | ||||||
| 	 * @throws IOException if the online mode could not be entered or the request | 	 * @throws Exception if the online mode could not be entered or the request | ||||||
| 	 *                     failed for some other reason | 	 *                   failed for some other reason | ||||||
| 	 * @since Envoy v0.2-alpha | 	 * @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())); | 		logger.info(String.format("Attempting connection to server %s:%d...", config.getServer(), config.getPort())); | ||||||
| 		socket = new Socket(config.getServer(), config.getPort()); | 		socket = new Socket(config.getServer(), config.getPort()); | ||||||
| 		logger.info("Successfully connected to server."); | 		logger.info("Successfully connected to server."); | ||||||
| @@ -47,14 +47,20 @@ public class Client { | |||||||
| 		logger.finest("Sending login credentials..."); | 		logger.finest("Sending login credentials..."); | ||||||
| 		SerializationUtils.writeBytesWithLength(credentials, socket.getOutputStream()); | 		SerializationUtils.writeBytesWithLength(credentials, socket.getOutputStream()); | ||||||
|  |  | ||||||
| 		// Read response (user object) | 		// Create message receiver | ||||||
| 		InputStream in = socket.getInputStream(); | 		Receiver receiver = new Receiver(socket.getInputStream()); | ||||||
|  |  | ||||||
| 		// Read object | 		// Register user creation processor | ||||||
| 		try { | 		receiver.registerProcessor(User.class, sender -> { logger.info("Acquired user object " + sender); this.sender = sender; }); | ||||||
| 			sender = SerializationUtils.read(in, User.class); |  | ||||||
| 		} catch (ClassNotFoundException e) { | 		// Start receiver | ||||||
| 			throw new IOException(e); | 		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; | 		online = true; | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								src/main/java/envoy/client/ObjectProcessor.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/main/java/envoy/client/ObjectProcessor.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | package envoy.client; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Project: <strong>envoy-client</strong><br> | ||||||
|  |  * File: <strong>ObjectProcessor.java</strong><br> | ||||||
|  |  * Created: <strong>30.12.2019</strong><br> | ||||||
|  |  *  | ||||||
|  |  * @author Kai S. K. Engelbart | ||||||
|  |  * @since Envoy v0.3-alpha | ||||||
|  |  */ | ||||||
|  | public interface ObjectProcessor<T> { | ||||||
|  |  | ||||||
|  | 	void process(T input); | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								src/main/java/envoy/client/Receiver.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/main/java/envoy/client/Receiver.java
									
									
									
									
									
										Normal file
									
								
							| @@ -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: <strong>envoy-client</strong><br> | ||||||
|  |  * File: <strong>Receiver.java</strong><br> | ||||||
|  |  * Created: <strong>30.12.2019</strong><br> | ||||||
|  |  *  | ||||||
|  |  * @author Kai S. K. Engelbart | ||||||
|  |  * @since Envoy v0.3-alpha | ||||||
|  |  */ | ||||||
|  | public class Receiver implements Runnable { | ||||||
|  |  | ||||||
|  | 	private InputStream				in; | ||||||
|  | 	private Map<Class<?>, 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 <T> void registerProcessor(Class<T> processorClass, ObjectProcessor<T> processor) { processors.put(processorClass, processor); } | ||||||
|  | } | ||||||
| @@ -101,6 +101,7 @@ public class Startup { | |||||||
| 			client.onlineInit(new LoginCredentials(userName, pass.toCharArray())); | 			client.onlineInit(new LoginCredentials(userName, pass.toCharArray())); | ||||||
| 		} catch (Exception e1) { | 		} catch (Exception e1) { | ||||||
| 			logger.warning("Could not connect to server. Trying offline mode..."); | 			logger.warning("Could not connect to server. Trying offline mode..."); | ||||||
|  | 			e1.printStackTrace(); | ||||||
| 			try { | 			try { | ||||||
| 				// Try entering offline mode | 				// Try entering offline mode | ||||||
| 				localDB.loadUsers(); | 				localDB.loadUsers(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user