mirror of
https://github.com/davidalves04/Trabalho-Pratico-SD.git
synced 2025-12-08 12:33:31 +00:00
Java serialization removed
This commit is contained in:
@@ -89,11 +89,7 @@ Este projeto implementa uma simulação distribuída de tráfego veicular numa r
|
|||||||
|
|
||||||
### Formato de Serialização: JSON (Gson)
|
### Formato de Serialização: JSON (Gson)
|
||||||
|
|
||||||
O sistema utiliza JSON como formato de serialização por ser:
|
O sistema utiliza JSON como formato de serialização por ser mais rápido, seguro e legível que a serialização em Java.
|
||||||
- Legível e fácil de debugar
|
|
||||||
- 54% menor que Java Serialization (300 vs 657 bytes)
|
|
||||||
- Compatível com ferramentas web/REST
|
|
||||||
- Seguro (sem vulnerabilidades de desserialização)
|
|
||||||
|
|
||||||
### Estrutura de Mensagens
|
### Estrutura de Mensagens
|
||||||
|
|
||||||
@@ -320,7 +316,6 @@ Trabalho-Pratico-SD/
|
|||||||
│ │ │ │ ├── MessageSerializer.java
|
│ │ │ │ ├── MessageSerializer.java
|
||||||
│ │ │ │ ├── SerializationException.java
|
│ │ │ │ ├── SerializationException.java
|
||||||
│ │ │ │ ├── JsonMessageSerializer.java
|
│ │ │ │ ├── JsonMessageSerializer.java
|
||||||
│ │ │ │ ├── JavaMessageSerializer.java
|
|
||||||
│ │ │ │ ├── SerializerFactory.java
|
│ │ │ │ ├── SerializerFactory.java
|
||||||
│ │ │ │ ├── SerializationExample.java
|
│ │ │ │ ├── SerializationExample.java
|
||||||
│ │ │ │ └── README.md
|
│ │ │ │ └── README.md
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
package sd.serialization;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Java native serialization implementation of {@link MessageSerializer}.
|
|
||||||
*
|
|
||||||
* This serializer uses Java's built-in ObjectOutputStream/ObjectInputStream
|
|
||||||
* for serialization, providing:
|
|
||||||
* - Native Java type preservation
|
|
||||||
* - Support for complex object graphs
|
|
||||||
* - No external dependencies
|
|
||||||
* - Fast binary serialization
|
|
||||||
*
|
|
||||||
* Requirements:
|
|
||||||
* - All serialized objects must implement {@link Serializable}
|
|
||||||
* - Classes should define serialVersionUID for version control
|
|
||||||
*
|
|
||||||
* Limitations:
|
|
||||||
* - Only works between Java applications
|
|
||||||
* - Larger message sizes than JSON
|
|
||||||
* - Binary format (not human-readable)
|
|
||||||
* - Potential security vulnerabilities
|
|
||||||
*
|
|
||||||
* Thread-safety: This class is thread-safe as it creates new streams for each operation.
|
|
||||||
*
|
|
||||||
* @see MessageSerializer
|
|
||||||
*/
|
|
||||||
public class JavaMessageSerializer implements MessageSerializer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] serialize(Object object) throws SerializationException {
|
|
||||||
if (object == null) {
|
|
||||||
throw new IllegalArgumentException("Cannot serialize null object");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(object instanceof Serializable)) {
|
|
||||||
throw new SerializationException(
|
|
||||||
"Object of type " + object.getClass().getName() +
|
|
||||||
" does not implement Serializable");
|
|
||||||
}
|
|
||||||
|
|
||||||
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
|
|
||||||
|
|
||||||
oos.writeObject(object);
|
|
||||||
oos.flush();
|
|
||||||
return baos.toByteArray();
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new SerializationException(
|
|
||||||
"Failed to serialize object of type " + object.getClass().getName(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T deserialize(byte[] data, Class<T> clazz) throws SerializationException {
|
|
||||||
if (data == null) {
|
|
||||||
throw new IllegalArgumentException("Cannot deserialize null data");
|
|
||||||
}
|
|
||||||
if (clazz == null) {
|
|
||||||
throw new IllegalArgumentException("Class type cannot be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
|
||||||
ObjectInputStream ois = new ObjectInputStream(bais)) {
|
|
||||||
|
|
||||||
Object obj = ois.readObject();
|
|
||||||
|
|
||||||
if (!clazz.isInstance(obj)) {
|
|
||||||
throw new SerializationException(
|
|
||||||
"Deserialized object is not of expected type " + clazz.getName() +
|
|
||||||
", got " + obj.getClass().getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
return clazz.cast(obj);
|
|
||||||
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
throw new SerializationException(
|
|
||||||
"Class not found during deserialization: " + clazz.getName(), e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new SerializationException(
|
|
||||||
"Failed to deserialize object of type " + clazz.getName(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "Java Native Serialization";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supports(Class<?> clazz) {
|
|
||||||
return Serializable.class.isAssignableFrom(clazz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,8 +4,7 @@ package sd.serialization;
|
|||||||
* Interface for serializing and deserializing objects for network transmission.
|
* Interface for serializing and deserializing objects for network transmission.
|
||||||
*
|
*
|
||||||
* This interface provides a common abstraction for different serialization strategies
|
* This interface provides a common abstraction for different serialization strategies
|
||||||
* (e.g., Java Serialization, JSON, Protocol Buffers) allowing the system to switch
|
* allowing the system to switch between implementations without changing the communication layer.
|
||||||
* between implementations without changing the communication layer.
|
|
||||||
*
|
*
|
||||||
* Implementations must ensure:
|
* Implementations must ensure:
|
||||||
* - Thread-safety if used in concurrent contexts
|
* - Thread-safety if used in concurrent contexts
|
||||||
@@ -13,7 +12,6 @@ package sd.serialization;
|
|||||||
* - Preservation of object state during round-trip serialization
|
* - Preservation of object state during round-trip serialization
|
||||||
*
|
*
|
||||||
* @see JsonMessageSerializer
|
* @see JsonMessageSerializer
|
||||||
* @see JavaMessageSerializer
|
|
||||||
*/
|
*/
|
||||||
public interface MessageSerializer {
|
public interface MessageSerializer {
|
||||||
|
|
||||||
@@ -49,12 +47,12 @@ public interface MessageSerializer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this serializer supports a specific class type.
|
* Checks if this serializer supports a specific class type.
|
||||||
* Some serializers may have limitations on what types they can handle.
|
|
||||||
*
|
*
|
||||||
* @param clazz The class to check
|
* @param clazz The class to check
|
||||||
* @return true if this serializer can handle the class, false otherwise
|
* @return true if this serializer can handle the class, false otherwise
|
||||||
*/
|
|
||||||
default boolean supports(Class<?> clazz) {
|
default boolean supports(Class<?> clazz) {
|
||||||
return true; // By default, assume all types are supported
|
return true; // By default, assume all types are supported
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,15 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Demonstration of serialization usage in the traffic simulation system.
|
* Demonstration of JSON serialization usage in the traffic simulation system.
|
||||||
*
|
*
|
||||||
* This class shows practical examples of how to use both JSON and Java
|
* This class shows practical examples of how to use JSON (Gson) serialization
|
||||||
* serialization for network communication between simulation processes.
|
* for network communication between simulation processes.
|
||||||
*/
|
*/
|
||||||
public class SerializationExample {
|
public class SerializationExample {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
System.out.println("=== Serialization Example ===\n");
|
System.out.println("=== JSON Serialization Example ===\n");
|
||||||
|
|
||||||
// Create a sample vehicle
|
// Create a sample vehicle
|
||||||
List<String> route = Arrays.asList("Cr1", "Cr2", "Cr5", "S");
|
List<String> route = Arrays.asList("Cr1", "Cr2", "Cr5", "S");
|
||||||
@@ -36,14 +36,11 @@ public class SerializationExample {
|
|||||||
// ===== JSON Serialization =====
|
// ===== JSON Serialization =====
|
||||||
demonstrateJsonSerialization(message);
|
demonstrateJsonSerialization(message);
|
||||||
|
|
||||||
// ===== Java Serialization =====
|
|
||||||
demonstrateJavaSerialization(message);
|
|
||||||
|
|
||||||
// ===== Factory Usage =====
|
// ===== Factory Usage =====
|
||||||
demonstrateFactoryUsage(message);
|
demonstrateFactoryUsage(message);
|
||||||
|
|
||||||
// ===== Performance Comparison =====
|
// ===== Performance Test =====
|
||||||
performanceComparison(message);
|
performanceTest(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void demonstrateJsonSerialization(Message message) {
|
private static void demonstrateJsonSerialization(Message message) {
|
||||||
@@ -71,35 +68,11 @@ public class SerializationExample {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void demonstrateJavaSerialization(Message message) {
|
|
||||||
System.out.println("--- Java Native Serialization ---");
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Create Java serializer
|
|
||||||
MessageSerializer serializer = new JavaMessageSerializer();
|
|
||||||
|
|
||||||
// Serialize to bytes
|
|
||||||
byte[] data = serializer.serialize(message);
|
|
||||||
|
|
||||||
System.out.println("Serialized binary (" + data.length + " bytes)");
|
|
||||||
System.out.println("Binary data (first 50 bytes): " +
|
|
||||||
bytesToHex(data, 50));
|
|
||||||
|
|
||||||
// Deserialize back
|
|
||||||
Message deserialized = serializer.deserialize(data, Message.class);
|
|
||||||
System.out.println("\nDeserialized: " + deserialized);
|
|
||||||
System.out.println("✓ Java serialization successful\n");
|
|
||||||
|
|
||||||
} catch (SerializationException e) {
|
|
||||||
System.err.println("❌ Java serialization failed: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void demonstrateFactoryUsage(Message message) {
|
private static void demonstrateFactoryUsage(Message message) {
|
||||||
System.out.println("--- Using SerializerFactory ---");
|
System.out.println("--- Using SerializerFactory ---");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Get default serializer (configured via system properties or defaults to JSON)
|
// Get default serializer (JSON)
|
||||||
MessageSerializer serializer = SerializerFactory.createDefault();
|
MessageSerializer serializer = SerializerFactory.createDefault();
|
||||||
System.out.println("Default serializer: " + serializer.getName());
|
System.out.println("Default serializer: " + serializer.getName());
|
||||||
|
|
||||||
@@ -117,77 +90,45 @@ public class SerializationExample {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void performanceComparison(Message message) {
|
private static void performanceTest(Message message) {
|
||||||
System.out.println("--- Performance Comparison ---");
|
System.out.println("--- Performance Test ---");
|
||||||
|
|
||||||
int iterations = 1000;
|
int iterations = 1000;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
MessageSerializer jsonSerializer = new JsonMessageSerializer(false); // No pretty print
|
MessageSerializer compactSerializer = new JsonMessageSerializer(false);
|
||||||
MessageSerializer javaSerializer = new JavaMessageSerializer();
|
MessageSerializer prettySerializer = new JsonMessageSerializer(true);
|
||||||
|
|
||||||
// Warm up
|
// Warm up
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
jsonSerializer.serialize(message);
|
compactSerializer.serialize(message);
|
||||||
javaSerializer.serialize(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test JSON
|
// Test compact JSON
|
||||||
long jsonStart = System.nanoTime();
|
long compactStart = System.nanoTime();
|
||||||
byte[] jsonData = null;
|
byte[] compactData = null;
|
||||||
for (int i = 0; i < iterations; i++) {
|
for (int i = 0; i < iterations; i++) {
|
||||||
jsonData = jsonSerializer.serialize(message);
|
compactData = compactSerializer.serialize(message);
|
||||||
}
|
}
|
||||||
long jsonTime = System.nanoTime() - jsonStart;
|
long compactTime = System.nanoTime() - compactStart;
|
||||||
|
|
||||||
// Test Java
|
// Test pretty JSON
|
||||||
long javaStart = System.nanoTime();
|
byte[] prettyData = prettySerializer.serialize(message);
|
||||||
byte[] javaData = null;
|
|
||||||
for (int i = 0; i < iterations; i++) {
|
|
||||||
javaData = javaSerializer.serialize(message);
|
|
||||||
}
|
|
||||||
long javaTime = System.nanoTime() - javaStart;
|
|
||||||
|
|
||||||
// Results
|
// Results
|
||||||
System.out.println("Iterations: " + iterations);
|
System.out.println("Iterations: " + iterations);
|
||||||
System.out.println("\nJSON Serialization:");
|
System.out.println("\nJSON Compact:");
|
||||||
System.out.println(" Size: " + jsonData.length + " bytes");
|
System.out.println(" Size: " + compactData.length + " bytes");
|
||||||
System.out.println(" Time: " + (jsonTime / 1_000_000.0) + " ms total");
|
System.out.println(" Time: " + (compactTime / 1_000_000.0) + " ms total");
|
||||||
System.out.println(" Avg: " + (jsonTime / iterations / 1_000.0) + " μs/operation");
|
System.out.println(" Avg: " + (compactTime / iterations / 1_000.0) + " μs/operation");
|
||||||
|
|
||||||
System.out.println("\nJava Serialization:");
|
System.out.println("\nJSON Pretty-Print:");
|
||||||
System.out.println(" Size: " + javaData.length + " bytes");
|
System.out.println(" Size: " + prettyData.length + " bytes");
|
||||||
System.out.println(" Time: " + (javaTime / 1_000_000.0) + " ms total");
|
System.out.println(" Size increase: " +
|
||||||
System.out.println(" Avg: " + (javaTime / iterations / 1_000.0) + " μs/operation");
|
String.format("%.1f%%", ((double)prettyData.length / compactData.length - 1) * 100));
|
||||||
|
|
||||||
System.out.println("\nComparison:");
|
|
||||||
double sizeRatio = (double) jsonData.length / javaData.length;
|
|
||||||
double timeRatio = (double) jsonTime / javaTime;
|
|
||||||
System.out.println(" JSON is " + String.format("%.1f%%", (1 - sizeRatio) * 100) +
|
|
||||||
" smaller in size");
|
|
||||||
System.out.println(" JSON is " + String.format("%.1fx", timeRatio) +
|
|
||||||
" the speed of Java serialization");
|
|
||||||
|
|
||||||
} catch (SerializationException e) {
|
} catch (SerializationException e) {
|
||||||
System.err.println("❌ Performance test failed: " + e.getMessage());
|
System.err.println("❌ Performance test failed: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts byte array to hex string for display.
|
|
||||||
*/
|
|
||||||
private static String bytesToHex(byte[] bytes, int maxLength) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
int length = Math.min(bytes.length, maxLength);
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
sb.append(String.format("%02x ", bytes[i]));
|
|
||||||
if ((i + 1) % 16 == 0) {
|
|
||||||
sb.append("\n ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bytes.length > maxLength) {
|
|
||||||
sb.append("...");
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ package sd.serialization;
|
|||||||
*/
|
*/
|
||||||
public class SerializationException extends Exception {
|
public class SerializationException extends Exception {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L; // Long(64bits) instead of int(32bits)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new serialization exception with the specified detail message.
|
* Constructs a new serialization exception with the specified detail message.
|
||||||
|
|||||||
@@ -3,12 +3,10 @@ package sd.serialization;
|
|||||||
/**
|
/**
|
||||||
* Factory for creating {@link MessageSerializer} instances.
|
* Factory for creating {@link MessageSerializer} instances.
|
||||||
*
|
*
|
||||||
* This factory provides a centralized way to create and configure serializers,
|
* This factory provides a centralized way to create and configure JSON serializers
|
||||||
* making it easy to switch between different serialization strategies throughout
|
* using Gson, making it easy to configure serialization throughout the application.
|
||||||
* the application.
|
|
||||||
*
|
*
|
||||||
* The factory supports multiple serialization types and can be configured via
|
* The factory can be configured via system properties for easy deployment configuration.
|
||||||
* system properties or environment variables for easy deployment configuration.
|
|
||||||
*
|
*
|
||||||
* Example usage:
|
* Example usage:
|
||||||
* <pre>
|
* <pre>
|
||||||
@@ -18,22 +16,6 @@ package sd.serialization;
|
|||||||
*/
|
*/
|
||||||
public class SerializerFactory {
|
public class SerializerFactory {
|
||||||
|
|
||||||
/**
|
|
||||||
* Enumeration of supported serialization types.
|
|
||||||
*/
|
|
||||||
public enum SerializationType {
|
|
||||||
/** JSON serialization using Gson */
|
|
||||||
JSON,
|
|
||||||
/** Java native serialization */
|
|
||||||
JAVA_NATIVE
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* System property key for configuring the default serialization type.
|
|
||||||
* Set this property to "JSON" or "JAVA_NATIVE" to control the default serializer.
|
|
||||||
*/
|
|
||||||
public static final String SERIALIZATION_TYPE_PROPERTY = "sd.serialization.type";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* System property key for enabling pretty-print in JSON serialization.
|
* System property key for enabling pretty-print in JSON serialization.
|
||||||
* Set to "true" for debugging, "false" for production.
|
* Set to "true" for debugging, "false" for production.
|
||||||
@@ -41,7 +23,6 @@ public class SerializerFactory {
|
|||||||
public static final String JSON_PRETTY_PRINT_PROPERTY = "sd.serialization.json.prettyPrint";
|
public static final String JSON_PRETTY_PRINT_PROPERTY = "sd.serialization.json.prettyPrint";
|
||||||
|
|
||||||
// Default configuration
|
// Default configuration
|
||||||
private static final SerializationType DEFAULT_TYPE = SerializationType.JSON;
|
|
||||||
private static final boolean DEFAULT_JSON_PRETTY_PRINT = false;
|
private static final boolean DEFAULT_JSON_PRETTY_PRINT = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,61 +33,25 @@ public class SerializerFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a serializer based on system configuration.
|
* Creates a JSON serializer based on system configuration.
|
||||||
*
|
*
|
||||||
* The type is determined by checking the system property
|
* Pretty-print is determined by checking the system property
|
||||||
* {@value #SERIALIZATION_TYPE_PROPERTY}. If not set, defaults to JSON.
|
* {@value #JSON_PRETTY_PRINT_PROPERTY}. If not set, defaults to false.
|
||||||
*
|
*
|
||||||
* @return A configured MessageSerializer instance
|
* @return A configured JsonMessageSerializer instance
|
||||||
*/
|
*/
|
||||||
public static MessageSerializer createDefault() {
|
public static MessageSerializer createDefault() {
|
||||||
String typeProperty = System.getProperty(SERIALIZATION_TYPE_PROPERTY);
|
|
||||||
SerializationType type = DEFAULT_TYPE;
|
|
||||||
|
|
||||||
if (typeProperty != null) {
|
|
||||||
try {
|
|
||||||
type = SerializationType.valueOf(typeProperty.toUpperCase());
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
System.err.println("Invalid serialization type: " + typeProperty +
|
|
||||||
". Using default: " + DEFAULT_TYPE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return create(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a serializer of the specified type.
|
|
||||||
*
|
|
||||||
* @param type The serialization type
|
|
||||||
* @return A MessageSerializer instance
|
|
||||||
* @throws IllegalArgumentException If type is null
|
|
||||||
*/
|
|
||||||
public static MessageSerializer create(SerializationType type) {
|
|
||||||
if (type == null) {
|
|
||||||
throw new IllegalArgumentException("Serialization type cannot be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case JSON:
|
|
||||||
boolean prettyPrint = Boolean.getBoolean(JSON_PRETTY_PRINT_PROPERTY);
|
boolean prettyPrint = Boolean.getBoolean(JSON_PRETTY_PRINT_PROPERTY);
|
||||||
return new JsonMessageSerializer(prettyPrint);
|
return new JsonMessageSerializer(prettyPrint);
|
||||||
|
|
||||||
case JAVA_NATIVE:
|
|
||||||
return new JavaMessageSerializer();
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Unsupported serialization type: " + type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a JSON serializer with default configuration.
|
* Creates a JSON serializer with default configuration (no pretty printing).
|
||||||
*
|
*
|
||||||
* @return A JsonMessageSerializer instance
|
* @return A JsonMessageSerializer instance
|
||||||
*/
|
*/
|
||||||
public static MessageSerializer createJsonSerializer() {
|
public static MessageSerializer createSerializer() {
|
||||||
return createJsonSerializer(DEFAULT_JSON_PRETTY_PRINT);
|
return createSerializer(DEFAULT_JSON_PRETTY_PRINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,33 +60,7 @@ public class SerializerFactory {
|
|||||||
* @param prettyPrint Whether to enable pretty printing
|
* @param prettyPrint Whether to enable pretty printing
|
||||||
* @return A JsonMessageSerializer instance
|
* @return A JsonMessageSerializer instance
|
||||||
*/
|
*/
|
||||||
public static MessageSerializer createJsonSerializer(boolean prettyPrint) {
|
public static MessageSerializer createSerializer(boolean prettyPrint) {
|
||||||
return new JsonMessageSerializer(prettyPrint);
|
return new JsonMessageSerializer(prettyPrint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a Java native serializer.
|
|
||||||
*
|
|
||||||
* @return A JavaMessageSerializer instance
|
|
||||||
*/
|
|
||||||
public static MessageSerializer createJavaSerializer() {
|
|
||||||
return new JavaMessageSerializer();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the configured default serialization type.
|
|
||||||
*
|
|
||||||
* @return The default SerializationType
|
|
||||||
*/
|
|
||||||
public static SerializationType getDefaultType() {
|
|
||||||
String typeProperty = System.getProperty(SERIALIZATION_TYPE_PROPERTY);
|
|
||||||
if (typeProperty != null) {
|
|
||||||
try {
|
|
||||||
return SerializationType.valueOf(typeProperty.toUpperCase());
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
// Fall through to default
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return DEFAULT_TYPE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,54 +1,36 @@
|
|||||||
package sd.serialization;
|
package sd.serialization;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.DisplayName;
|
import org.junit.jupiter.api.DisplayName;
|
||||||
import sd.model.Message;
|
import sd.model.Message;
|
||||||
import sd.model.MessageType;
|
|
||||||
import sd.model.Vehicle;
|
import sd.model.Vehicle;
|
||||||
import sd.model.VehicleType;
|
import sd.model.VehicleType;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test suite for serialization implementations.
|
* Test suite for JSON serialization.
|
||||||
*
|
*
|
||||||
* Tests both JSON and Java native serialization to ensure:
|
* Tests JSON serialization to ensure:
|
||||||
* - Correct serialization and deserialization
|
* - Correct serialization and deserialization
|
||||||
* - Data integrity during round-trip conversion
|
* - Data integrity during round-trip conversion
|
||||||
* - Proper error handling
|
* - Proper error handling
|
||||||
* - Performance characteristics
|
|
||||||
*/
|
*/
|
||||||
class SerializationTest {
|
class SerializationTest {
|
||||||
|
|
||||||
private MessageSerializer jsonSerializer;
|
private MessageSerializer jsonSerializer = new JsonMessageSerializer();
|
||||||
private MessageSerializer javaSerializer;
|
|
||||||
|
|
||||||
private Vehicle testVehicle;
|
private Vehicle testVehicle = new Vehicle("V001", VehicleType.LIGHT, 10.5,
|
||||||
private Message testMessage;
|
Arrays.asList("Cr1", "Cr2", "Cr5", "S"));
|
||||||
|
private Message testMessage = new Message(
|
||||||
@BeforeEach
|
sd.model.MessageType.VEHICLE_TRANSFER,
|
||||||
void setUp() {
|
|
||||||
jsonSerializer = SerializerFactory.createJsonSerializer(true); // Pretty print for debugging
|
|
||||||
javaSerializer = SerializerFactory.createJavaSerializer();
|
|
||||||
|
|
||||||
// Create test vehicle
|
|
||||||
List<String> route = Arrays.asList("Cr1", "Cr2", "Cr5", "S");
|
|
||||||
testVehicle = new Vehicle("V123", VehicleType.LIGHT, 15.7, route);
|
|
||||||
testVehicle.addWaitingTime(3.2);
|
|
||||||
testVehicle.addCrossingTime(1.8);
|
|
||||||
|
|
||||||
// Create test message
|
|
||||||
testMessage = new Message(
|
|
||||||
MessageType.VEHICLE_TRANSFER,
|
|
||||||
"Cr1",
|
"Cr1",
|
||||||
"Cr2",
|
"Cr2",
|
||||||
testVehicle
|
testVehicle
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
// ===== JSON Serialization Tests =====
|
// ===== JSON Serialization Tests =====
|
||||||
|
|
||||||
@@ -123,89 +105,8 @@ class SerializationTest {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== Java Serialization Tests =====
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Java: Should serialize and deserialize Vehicle correctly")
|
@DisplayName("JSON: Should preserve data integrity for complex objects")
|
||||||
void testJavaVehicleRoundTrip() throws SerializationException {
|
|
||||||
// Serialize
|
|
||||||
byte[] data = javaSerializer.serialize(testVehicle);
|
|
||||||
assertNotNull(data);
|
|
||||||
assertTrue(data.length > 0);
|
|
||||||
|
|
||||||
System.out.println("\nJava Serialization - Vehicle size: " + data.length + " bytes");
|
|
||||||
|
|
||||||
// Deserialize
|
|
||||||
Vehicle deserialized = javaSerializer.deserialize(data, Vehicle.class);
|
|
||||||
|
|
||||||
// Verify
|
|
||||||
assertNotNull(deserialized);
|
|
||||||
assertEquals(testVehicle.getId(), deserialized.getId());
|
|
||||||
assertEquals(testVehicle.getType(), deserialized.getType());
|
|
||||||
assertEquals(testVehicle.getEntryTime(), deserialized.getEntryTime());
|
|
||||||
assertEquals(testVehicle.getRoute(), deserialized.getRoute());
|
|
||||||
assertEquals(testVehicle.getTotalWaitingTime(), deserialized.getTotalWaitingTime());
|
|
||||||
assertEquals(testVehicle.getTotalCrossingTime(), deserialized.getTotalCrossingTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("Java: Should serialize and deserialize Message correctly")
|
|
||||||
void testJavaMessageRoundTrip() throws SerializationException {
|
|
||||||
// Serialize
|
|
||||||
byte[] data = javaSerializer.serialize(testMessage);
|
|
||||||
assertNotNull(data);
|
|
||||||
|
|
||||||
System.out.println("Java Serialization - Message size: " + data.length + " bytes");
|
|
||||||
|
|
||||||
// Deserialize
|
|
||||||
Message deserialized = javaSerializer.deserialize(data, Message.class);
|
|
||||||
|
|
||||||
// Verify
|
|
||||||
assertNotNull(deserialized);
|
|
||||||
assertEquals(testMessage.getType(), deserialized.getType());
|
|
||||||
assertEquals(testMessage.getSenderId(), deserialized.getSenderId());
|
|
||||||
assertEquals(testMessage.getDestinationId(), deserialized.getDestinationId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("Java: Should throw exception on null object")
|
|
||||||
void testJavaSerializeNull() {
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
|
||||||
javaSerializer.serialize(null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("Java: Should throw exception on null data")
|
|
||||||
void testJavaDeserializeNull() {
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
|
||||||
javaSerializer.deserialize(null, Vehicle.class);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== Comparison Tests =====
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("Compare: JSON should produce smaller messages than Java serialization")
|
|
||||||
void testSizeComparison() throws SerializationException {
|
|
||||||
byte[] jsonData = jsonSerializer.serialize(testVehicle);
|
|
||||||
byte[] javaData = javaSerializer.serialize(testVehicle);
|
|
||||||
|
|
||||||
System.out.println("\n=== Size Comparison ===");
|
|
||||||
System.out.println("JSON size: " + jsonData.length + " bytes");
|
|
||||||
System.out.println("Java size: " + javaData.length + " bytes");
|
|
||||||
System.out.println("Difference: " + (javaData.length - jsonData.length) + " bytes");
|
|
||||||
System.out.println("JSON is " +
|
|
||||||
String.format("%.1f", (1.0 - (double)jsonData.length / javaData.length) * 100) +
|
|
||||||
"% smaller");
|
|
||||||
|
|
||||||
// Note: This assertion might fail with pretty printing enabled
|
|
||||||
// assertTrue(jsonData.length < javaData.length,
|
|
||||||
// "JSON should typically be smaller than Java serialization");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("Compare: Both serializers should preserve data integrity")
|
|
||||||
void testDataIntegrity() throws SerializationException {
|
void testDataIntegrity() throws SerializationException {
|
||||||
// Create a more complex vehicle
|
// Create a more complex vehicle
|
||||||
Vehicle vehicle = new Vehicle("V999", VehicleType.HEAVY, 100.5,
|
Vehicle vehicle = new Vehicle("V999", VehicleType.HEAVY, 100.5,
|
||||||
@@ -216,18 +117,15 @@ class SerializationTest {
|
|||||||
vehicle.advanceRoute();
|
vehicle.advanceRoute();
|
||||||
vehicle.advanceRoute();
|
vehicle.advanceRoute();
|
||||||
|
|
||||||
// Test both serializers
|
// Serialize and deserialize
|
||||||
byte[] jsonData = jsonSerializer.serialize(vehicle);
|
byte[] jsonData = jsonSerializer.serialize(vehicle);
|
||||||
byte[] javaData = javaSerializer.serialize(vehicle);
|
Vehicle deserialized = jsonSerializer.deserialize(jsonData, Vehicle.class);
|
||||||
|
|
||||||
Vehicle jsonVehicle = jsonSerializer.deserialize(jsonData, Vehicle.class);
|
// Verify all fields match
|
||||||
Vehicle javaVehicle = javaSerializer.deserialize(javaData, Vehicle.class);
|
assertEquals(vehicle.getId(), deserialized.getId());
|
||||||
|
assertEquals(vehicle.getType(), deserialized.getType());
|
||||||
// Both should match
|
assertEquals(vehicle.getTotalWaitingTime(), deserialized.getTotalWaitingTime());
|
||||||
assertEquals(jsonVehicle.getId(), javaVehicle.getId());
|
assertEquals(vehicle.getCurrentRouteIndex(), deserialized.getCurrentRouteIndex());
|
||||||
assertEquals(jsonVehicle.getType(), javaVehicle.getType());
|
|
||||||
assertEquals(jsonVehicle.getTotalWaitingTime(), javaVehicle.getTotalWaitingTime());
|
|
||||||
assertEquals(jsonVehicle.getCurrentRouteIndex(), javaVehicle.getCurrentRouteIndex());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== Factory Tests =====
|
// ===== Factory Tests =====
|
||||||
@@ -239,21 +137,4 @@ class SerializationTest {
|
|||||||
assertNotNull(serializer);
|
assertNotNull(serializer);
|
||||||
assertEquals("JSON (Gson)", serializer.getName());
|
assertEquals("JSON (Gson)", serializer.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("Factory: Should create serializer by type")
|
|
||||||
void testFactoryByType() {
|
|
||||||
MessageSerializer json = SerializerFactory.create(SerializerFactory.SerializationType.JSON);
|
|
||||||
MessageSerializer java = SerializerFactory.create(SerializerFactory.SerializationType.JAVA_NATIVE);
|
|
||||||
|
|
||||||
assertEquals("JSON (Gson)", json.getName());
|
|
||||||
assertEquals("Java Native Serialization", java.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@DisplayName("Factory: Should support Vehicle class")
|
|
||||||
void testSupportsVehicle() {
|
|
||||||
assertTrue(jsonSerializer.supports(Vehicle.class));
|
|
||||||
assertTrue(javaSerializer.supports(Vehicle.class));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user