Added writing capabilities to ObjectProcessor, completed db integration
At this moment the client is not able to receive to objects sent consecutively. This will be worked on in a future commit and should be fixed before merging this branch into develop.
This commit is contained in:
parent
597385c950
commit
26fc4374ca
5
pom.xml
5
pom.xml
@ -33,6 +33,11 @@
|
|||||||
<artifactId>hibernate-core</artifactId>
|
<artifactId>hibernate-core</artifactId>
|
||||||
<version>5.4.10.Final</version>
|
<version>5.4.10.Final</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
<version>42.2.9</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
package envoy.server;
|
package envoy.server;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import envoy.data.Contacts;
|
||||||
import envoy.data.LoginCredentials;
|
import envoy.data.LoginCredentials;
|
||||||
import envoy.data.User;
|
import envoy.data.User;
|
||||||
|
import envoy.server.net.ObjectWriteProxy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This {@link ObjectProcessor} handles {@link LoginCredentials}.<br>
|
* This {@link ObjectProcessor} handles {@link LoginCredentials}.<br>
|
||||||
@ -13,7 +18,7 @@ import envoy.data.User;
|
|||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
* @since Envoy Server Standalone v0.1-alpha
|
* @since Envoy Server Standalone v0.1-alpha
|
||||||
*/
|
*/
|
||||||
public class LoginCredentialProcessor implements ObjectProcessor<LoginCredentials, User> {
|
public class LoginCredentialProcessor implements ObjectProcessor<LoginCredentials> {
|
||||||
|
|
||||||
// TODO: Acquire user IDs from database
|
// TODO: Acquire user IDs from database
|
||||||
private static long currentUserId = 1;
|
private static long currentUserId = 1;
|
||||||
@ -22,10 +27,20 @@ public class LoginCredentialProcessor implements ObjectProcessor<LoginCredential
|
|||||||
public Class<LoginCredentials> getInputClass() { return LoginCredentials.class; }
|
public Class<LoginCredentials> getInputClass() { return LoginCredentials.class; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User process(LoginCredentials input, long socketId) {
|
public void process(LoginCredentials input, long socketId, ObjectWriteProxy writeProxy) throws IOException {
|
||||||
System.out.println(String.format("Received login credentials %s from socket ID %d", input, socketId));
|
System.out.println(String.format("Received login credentials %s from socket ID %d", input, socketId));
|
||||||
|
|
||||||
|
// Create user
|
||||||
User user = new User(currentUserId++, input.getName());
|
User user = new User(currentUserId++, input.getName());
|
||||||
ConnectionManager.getInstance().registerUser(socketId, user.getId());
|
ConnectionManager.getInstance().registerUser(socketId, user.getId());
|
||||||
return user;
|
|
||||||
|
// Create contacts
|
||||||
|
Contacts contacts = new Contacts(user.getId(), new ArrayList<>());
|
||||||
|
|
||||||
|
// Complete handshake
|
||||||
|
System.out.println("Sending user...");
|
||||||
|
writeProxy.write(socketId, user);
|
||||||
|
System.out.println("Sending contacts...");
|
||||||
|
writeProxy.write(socketId, contacts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package envoy.server;
|
package envoy.server;
|
||||||
|
|
||||||
import envoy.data.Message;
|
import envoy.data.Message;
|
||||||
|
import envoy.server.net.ObjectWriteProxy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This {@link ObjectProcessor} handles incoming {@link Message}s.<br>
|
* This {@link ObjectProcessor} handles incoming {@link Message}s.<br>
|
||||||
@ -12,13 +13,13 @@ import envoy.data.Message;
|
|||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
* @since Envoy Server Standalone v0.1-alpha
|
* @since Envoy Server Standalone v0.1-alpha
|
||||||
*/
|
*/
|
||||||
public class MessageProcessor implements ObjectProcessor<Message, Void> {
|
public class MessageProcessor implements ObjectProcessor<Message> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<Message> getInputClass() { return Message.class; }
|
public Class<Message> getInputClass() { return Message.class; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void process(Message message, long socketId) {
|
public void process(Message message, long socketId, ObjectWriteProxy writeProxy) {
|
||||||
|
|
||||||
// TODO: Send message to recipient if online
|
// TODO: Send message to recipient if online
|
||||||
ConnectionManager connectionManager = ConnectionManager.getInstance();
|
ConnectionManager connectionManager = ConnectionManager.getInstance();
|
||||||
@ -27,6 +28,5 @@ public class MessageProcessor implements ObjectProcessor<Message, Void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add message to database
|
// TODO: Add message to database
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package envoy.server;
|
package envoy.server;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import envoy.server.net.ObjectWriteProxy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface defines methods for processing objects of a specific
|
* This interface defines methods for processing objects of a specific
|
||||||
* type incoming from a client.<br>
|
* type incoming from a client.<br>
|
||||||
@ -10,13 +14,12 @@ package envoy.server;
|
|||||||
*
|
*
|
||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
* @param <T> type of the request object
|
* @param <T> type of the request object
|
||||||
* @param <U> type of the response object
|
|
||||||
* @since Envoy Server Standalone v0.1-alpha
|
* @since Envoy Server Standalone v0.1-alpha
|
||||||
*/
|
*/
|
||||||
public interface ObjectProcessor<T, U> {
|
public interface ObjectProcessor<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the Class of the request object
|
* @return the class of the request object
|
||||||
* @since Envoy Server Standalone v0.1-alpha
|
* @since Envoy Server Standalone v0.1-alpha
|
||||||
*/
|
*/
|
||||||
Class<T> getInputClass();
|
Class<T> getInputClass();
|
||||||
@ -27,5 +30,5 @@ public interface ObjectProcessor<T, U> {
|
|||||||
* @return the response object
|
* @return the response object
|
||||||
* @since Envoy Server Standalone v0.1-alpha
|
* @since Envoy Server Standalone v0.1-alpha
|
||||||
*/
|
*/
|
||||||
U process(T input, long socketId);
|
void process(T input, long socketId, ObjectWriteProxy writeProxy) throws IOException;
|
||||||
}
|
}
|
@ -4,6 +4,7 @@ import java.util.Date;
|
|||||||
|
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.NamedQueries;
|
import javax.persistence.NamedQueries;
|
||||||
import javax.persistence.NamedQuery;
|
import javax.persistence.NamedQuery;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
@ -28,8 +29,12 @@ import envoy.data.MessageBuilder;
|
|||||||
@Entity
|
@Entity
|
||||||
@Table(name = "messages")
|
@Table(name = "messages")
|
||||||
@NamedQueries(
|
@NamedQueries(
|
||||||
{ @NamedQuery(query = "SELECT m FROM Message m WHERE m.recipient =:recipient AND m.state = 1", name = "getUnreadMessages"), @NamedQuery(
|
{ @NamedQuery(
|
||||||
query = "SELECT m FROM Message m WHERE m.sender =:sender AND m.state = :state",
|
query = "SELECT m FROM Message m WHERE m.recipient =:recipient AND m.status = envoy.data.Message$MessageStatus.SENT",
|
||||||
|
name = "getUnreadMessages"
|
||||||
|
),
|
||||||
|
@NamedQuery(
|
||||||
|
query = "SELECT m FROM Message m WHERE m.sender =:sender AND m.status = :status",
|
||||||
name = "find read messages"//TODO do we need this namedQuery?
|
name = "find read messages"//TODO do we need this namedQuery?
|
||||||
), @NamedQuery(query = "SELECT m FROM Message m WHERE m.id = :messageId", name = "get message") }//TODO do we need this namedQuery?
|
), @NamedQuery(query = "SELECT m FROM Message m WHERE m.id = :messageId", name = "get message") }//TODO do we need this namedQuery?
|
||||||
)
|
)
|
||||||
@ -37,13 +42,22 @@ public class Message {
|
|||||||
|
|
||||||
@Id
|
@Id
|
||||||
private long id;
|
private long id;
|
||||||
private User sender, recipient;
|
|
||||||
|
@ManyToOne
|
||||||
|
private User sender;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private User recipient;
|
||||||
|
|
||||||
@Temporal(TemporalType.TIMESTAMP)
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
private Date creationDate;
|
private Date creationDate;
|
||||||
|
|
||||||
@Temporal(TemporalType.TIMESTAMP)
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
private Date receivedDate;
|
private Date receivedDate;
|
||||||
|
|
||||||
@Temporal(TemporalType.TIMESTAMP)
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
private Date readDate;
|
private Date readDate;
|
||||||
|
|
||||||
private envoy.data.Message.MessageStatus status;
|
private envoy.data.Message.MessageStatus status;
|
||||||
private String text;
|
private String text;
|
||||||
private byte[] attachment;
|
private byte[] attachment;
|
||||||
|
@ -3,6 +3,7 @@ package envoy.server.data;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.persistence.ElementCollection;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.GenerationType;
|
import javax.persistence.GenerationType;
|
||||||
@ -27,7 +28,7 @@ import javax.persistence.TemporalType;
|
|||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "users")
|
@Table(name = "users")
|
||||||
@NamedQuery(query = "SELECT u FROM DBUser u WHERE u.id = :id", name = "getUserById")
|
@NamedQuery(query = "SELECT u FROM User u WHERE u.id = :id", name = "getUserById")
|
||||||
public class User {
|
public class User {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@ -35,9 +36,12 @@ public class User {
|
|||||||
private long id;
|
private long id;
|
||||||
private String name;
|
private String name;
|
||||||
private byte[] passwordHash;
|
private byte[] passwordHash;
|
||||||
|
|
||||||
@Temporal(TemporalType.TIMESTAMP)
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
private Date lastSeen;
|
private Date lastSeen;
|
||||||
private envoy.data.User.UserStatus status;
|
private envoy.data.User.UserStatus status;
|
||||||
|
|
||||||
|
@ElementCollection
|
||||||
private List<User> contacts;
|
private List<User> contacts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package envoy.server.net;
|
package envoy.server.net;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import com.jenkov.nioserver.IMessageProcessor;
|
import com.jenkov.nioserver.IMessageProcessor;
|
||||||
@ -25,7 +23,7 @@ import envoy.server.ObjectProcessor;
|
|||||||
*/
|
*/
|
||||||
public class ObjectMessageProcessor implements IMessageProcessor {
|
public class ObjectMessageProcessor implements IMessageProcessor {
|
||||||
|
|
||||||
private final Set<ObjectProcessor<?, ?>> processors;
|
private final Set<ObjectProcessor<?>> processors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The constructor to set the {@link ObjectProcessor}s.
|
* The constructor to set the {@link ObjectProcessor}s.
|
||||||
@ -33,9 +31,7 @@ public class ObjectMessageProcessor implements IMessageProcessor {
|
|||||||
* @param processors the {@link ObjectProcessor} to set
|
* @param processors the {@link ObjectProcessor} to set
|
||||||
* @since Envoy Server Standalone v0.1-alpha
|
* @since Envoy Server Standalone v0.1-alpha
|
||||||
*/
|
*/
|
||||||
public ObjectMessageProcessor(Set<ObjectProcessor<?, ?>> processors) {
|
public ObjectMessageProcessor(Set<ObjectProcessor<?>> processors) { this.processors = processors; }
|
||||||
this.processors = processors;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
@ -45,24 +41,16 @@ public class ObjectMessageProcessor implements IMessageProcessor {
|
|||||||
System.out.println("Read object: " + obj.toString());
|
System.out.println("Read object: " + obj.toString());
|
||||||
|
|
||||||
// Process object
|
// Process object
|
||||||
processors.stream().filter(p -> p.getInputClass().isInstance(obj)).forEach((@SuppressWarnings("rawtypes") ObjectProcessor p) -> {
|
processors.stream()
|
||||||
Object responseObj = p.process(p.getInputClass().cast(obj), message.socketId);
|
.filter(p -> p.getInputClass().isInstance(obj))
|
||||||
if (responseObj != null) {
|
.forEach((@SuppressWarnings(
|
||||||
// Create message targeted at the client
|
"rawtypes"
|
||||||
Message response = writeProxy.getMessage();
|
) ObjectProcessor p) -> {
|
||||||
response.socketId = message.socketId;
|
try {
|
||||||
|
p.process(p.getInputClass().cast(obj), message.socketId, new ObjectWriteProxy(writeProxy));
|
||||||
// Serialize object to byte array
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
try (ObjectOutputStream oout = new ObjectOutputStream(baos)) {
|
|
||||||
oout.writeObject(responseObj);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
byte[] objBytes = baos.toByteArray();
|
|
||||||
response.writeToMessage(objBytes);
|
|
||||||
writeProxy.enqueue(response);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} catch (IOException | ClassNotFoundException e) {
|
} catch (IOException | ClassNotFoundException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
34
src/main/java/envoy/server/net/ObjectWriteProxy.java
Normal file
34
src/main/java/envoy/server/net/ObjectWriteProxy.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package envoy.server.net;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.jenkov.nioserver.Message;
|
||||||
|
import com.jenkov.nioserver.WriteProxy;
|
||||||
|
|
||||||
|
import envoy.util.SerializationUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project: <strong>envoy-server-standalone</strong><br>
|
||||||
|
* File: <strong>ObjectWriteProxy.java</strong><br>
|
||||||
|
* Created: <strong>04.01.2020</strong><br>
|
||||||
|
*
|
||||||
|
* @author Kai S. K. Engelbart
|
||||||
|
* @since Envoy Server Standalone v0.1-alpha
|
||||||
|
*/
|
||||||
|
public class ObjectWriteProxy {
|
||||||
|
|
||||||
|
private final WriteProxy writeProxy;
|
||||||
|
|
||||||
|
public ObjectWriteProxy(WriteProxy writeProxy) { this.writeProxy = writeProxy; }
|
||||||
|
|
||||||
|
public void write(long recipientSocketId, Object obj) throws IOException {
|
||||||
|
// Create message targeted at the client
|
||||||
|
Message response = writeProxy.getMessage();
|
||||||
|
response.socketId = recipientSocketId;
|
||||||
|
|
||||||
|
// Serialize object to byte array
|
||||||
|
byte[] objBytes = SerializationUtils.writeToByteArray(obj);
|
||||||
|
response.writeToMessage(objBytes);
|
||||||
|
writeProxy.enqueue(response);
|
||||||
|
}
|
||||||
|
}
|
29
src/main/resources/META-INF/persistence.xml
Normal file
29
src/main/resources/META-INF/persistence.xml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
|
||||||
|
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
|
||||||
|
version="2.1">
|
||||||
|
|
||||||
|
<persistence-unit name="envoy"
|
||||||
|
transaction-type="RESOURCE_LOCAL">
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<property name="javax.persistence.jdbc.driver"
|
||||||
|
value="org.postgresql.Driver" /> <!-- DB Driver -->
|
||||||
|
<property name="javax.persistence.jdbc.url"
|
||||||
|
value="jdbc:postgresql://localhost/envoy" /> <!-- BD Mane -->
|
||||||
|
<property name="javax.persistence.jdbc.user" value="envoy" /> <!-- DB User -->
|
||||||
|
<property name="javax.persistence.jdbc.password"
|
||||||
|
value="envoy" /> <!-- DB Password -->
|
||||||
|
|
||||||
|
<property name="hibernate.dialect"
|
||||||
|
value="org.hibernate.dialect.PostgreSQL95Dialect" /> <!-- DB Dialect -->
|
||||||
|
<property name="hibernate.hbm2ddl.auto" value="update" /> <!-- create / create-drop / update -->
|
||||||
|
|
||||||
|
<property name="hibernate.show_sql" value="true" /> <!-- Show SQL in console -->
|
||||||
|
<property name="hibernate.format_sql" value="true" /> <!-- Show SQL formatted -->
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</persistence-unit>
|
||||||
|
|
||||||
|
</persistence>
|
Reference in New Issue
Block a user