Receiving objects from server on separate thread
This commit is contained in:
		| @@ -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; | ||||
|   | ||||
							
								
								
									
										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())); | ||||
| 		} catch (Exception e1) { | ||||
| 			logger.warning("Could not connect to server. Trying offline mode..."); | ||||
| 			e1.printStackTrace(); | ||||
| 			try { | ||||
| 				// Try entering offline mode | ||||
| 				localDB.loadUsers(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user