diff --git a/core-java-modules/core-java-serialization/README.md b/core-java-modules/core-java-serialization/README.md new file mode 100644 index 0000000000..ed8f8dc1c6 --- /dev/null +++ b/core-java-modules/core-java-serialization/README.md @@ -0,0 +1,10 @@ +## Core Java Serialization + +### Relevant Articles: + +- [Guide to the Externalizable Interface in Java](http://www.baeldung.com/java-externalizable) +- [Introduction to Java Serialization](http://www.baeldung.com/java-serialization) +- [Deserialization Vulnerabilities in Java](https://www.baeldung.com/java-deserialization-vulnerabilities) +- [Serialization Validation in Java](https://www.baeldung.com/java-validate-serializable) +- [What Is the serialVersionUID?](https://www.baeldung.com/java-serial-version-uid) +- [Java Serialization: readObject() vs. readResolve()](https://www.baeldung.com/java-serialization-readobject-vs-readresolve) diff --git a/core-java-modules/core-java-serialization/pom.xml b/core-java-modules/core-java-serialization/pom.xml new file mode 100644 index 0000000000..fde91779f7 --- /dev/null +++ b/core-java-modules/core-java-serialization/pom.xml @@ -0,0 +1,178 @@ + + + 4.0.0 + core-java-serialization + core-java-serialization + jar + + + com.ossez.core-java-modules + core-java-modules + 0.0.2-SNAPSHOT + + + + + org.unix4j + unix4j-command + ${unix4j.version} + + + com.googlecode.grep4j + grep4j + ${grep4j.version} + + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + log4j + log4j + ${log4j.version} + + + org.springframework + spring-core + ${spring.core.version} + + + org.springframework + spring-core + ${spring.core.version} + test + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + core-java-serialization + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + ${project.build.directory}/libs + + + + + + org.codehaus.mojo + exec-maven-plugin + + java + com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed + + -Xmx300m + -XX:+UseParallelGC + -classpath + + com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed + + + + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven-javadoc-plugin.version} + + 17 + + + + + + + + integration + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + **/*ManualTest.java + + + **/*IntegrationTest.java + **/*IntTest.java + + + + + + + json + + + + + org.codehaus.mojo + exec-maven-plugin + + + run-benchmarks + + none + + exec + + + test + java + + -classpath + + org.openjdk.jmh.Main + .* + + + + + + + + + + + + 0.4 + 1.8.7 + 1.1 + 3.6.0 + 4.3.20.RELEASE + + + \ No newline at end of file diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/AppleProduct.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/AppleProduct.java new file mode 100644 index 0000000000..a10499b362 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/AppleProduct.java @@ -0,0 +1,30 @@ +package com.baeldung.deserialization; + +import java.io.Serializable; + +public class AppleProduct implements Serializable { + + private static final long serialVersionUID = 1234567L; // user-defined (i.e. not default or generated) + // private static final long serialVersionUID = 7654321L; // user-defined (i.e. not default or generated) + + public String headphonePort; + public String thunderboltPort; + public String lightningPort; + + public String getHeadphonePort() { + return headphonePort; + } + + public String getThunderboltPort() { + return thunderboltPort; + } + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public String getLightningPort() { + return lightningPort; + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/DefaultSerial.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/DefaultSerial.java new file mode 100644 index 0000000000..ddfef9a1d2 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/DefaultSerial.java @@ -0,0 +1,15 @@ +package com.baeldung.deserialization; + +import java.io.IOException; +import java.io.Serializable; + +public class DefaultSerial implements Serializable { + + private String name; + + public static void main(String[] args) throws IOException, ClassNotFoundException { + String digest = "rO0ABXNyACpjb20uYmFlbGR1bmcuZGVzZXJpY" + + "WxpemF0aW9uLkRlZmF1bHRTZXJpYWx9iVz3Lz/mdAIAAHhw"; + DefaultSerial instance = (DefaultSerial) DeserializationUtility.deSerializeObjectFromString(digest); + } +} diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/DeserializationUtility.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/DeserializationUtility.java new file mode 100644 index 0000000000..ad8e929898 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/DeserializationUtility.java @@ -0,0 +1,28 @@ +package com.baeldung.deserialization; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.Base64; + +public class DeserializationUtility { + + public static void main(String[] args) throws ClassNotFoundException, IOException { + + String serializedObj = "rO0ABXNyACljb20uYmFlbGR1bmcuZGVzZXJpYWxpemF0aW9uLkFwcGxlUHJvZHVjdAAAAAAAEtaHAgADTAANaGVhZHBob25lUG9ydHQAEkxqYXZhL2xhbmcvU3RyaW5nO0wADWxpZ2h0bmluZ1BvcnRxAH4AAUwAD3RodW5kZXJib2x0UG9ydHEAfgABeHB0ABFoZWFkcGhvbmVQb3J0MjAyMHQAEWxpZ2h0bmluZ1BvcnQyMDIwdAATdGh1bmRlcmJvbHRQb3J0MjAyMA=="; + System.out.println("Deserializing AppleProduct..."); + AppleProduct deserializedObj = (AppleProduct) deSerializeObjectFromString(serializedObj); + System.out.println("Headphone port of AppleProduct:" + deserializedObj.getHeadphonePort()); + System.out.println("Thunderbolt port of AppleProduct:" + deserializedObj.getThunderboltPort()); + System.out.println("LightningPort port of AppleProduct:" + deserializedObj.getLightningPort()); + } + + public static Object deSerializeObjectFromString(String s) throws IOException, ClassNotFoundException { + byte[] data = Base64.getDecoder().decode(s); + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data)); + Object o = ois.readObject(); + ois.close(); + return o; + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/SerializationUtility.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/SerializationUtility.java new file mode 100644 index 0000000000..aa7f66659a --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/deserialization/SerializationUtility.java @@ -0,0 +1,31 @@ +package com.baeldung.deserialization; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Base64; + +public class SerializationUtility { + + public static void main(String[] args) throws ClassNotFoundException, IOException { + + AppleProduct macBook = new AppleProduct(); + macBook.headphonePort = "headphonePort2020"; + macBook.thunderboltPort = "thunderboltPort2020"; + macBook.lightningPort = "lightningPort2020"; + + String serializedObj = serializeObjectToString(macBook); + System.out.println("Serialized AppleProduct object to string:"); + System.out.println(serializedObj); + } + + public static String serializeObjectToString(Serializable o) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(o); + oos.close(); + return Base64.getEncoder().encodeToString(baos.toByteArray()); + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/externalizable/Community.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/externalizable/Community.java new file mode 100644 index 0000000000..bdbec9f547 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/externalizable/Community.java @@ -0,0 +1,23 @@ +package com.baeldung.externalizable; + +import java.io.*; + +public class Community implements Serializable { + + private int id; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + @Override + public String toString() { + return "Community{" + + "id=" + id + + '}'; + } +} diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/externalizable/Country.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/externalizable/Country.java new file mode 100644 index 0000000000..9fa95002f5 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/externalizable/Country.java @@ -0,0 +1,62 @@ +package com.baeldung.externalizable; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + +public class Country implements Externalizable { + + private static final long serialVersionUID = 1L; + + private String name; + private String capital; + private int code; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCapital() { + return capital; + } + + public void setCapital(String capital) { + this.capital = capital; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + @Override + public void writeExternal(ObjectOutput out) throws IOException { + out.writeUTF(name); + out.writeUTF(capital); + out.writeInt(code); + } + + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + this.name = in.readUTF(); + this.capital = in.readUTF(); + this.code = in.readInt(); + } + + @Override + public String toString() { + return "Country{" + + "name='" + name + '\'' + + ", capital='" + capital + '\'' + + ", code=" + code + + '}'; + } +} diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/externalizable/Region.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/externalizable/Region.java new file mode 100644 index 0000000000..3ddb694291 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/externalizable/Region.java @@ -0,0 +1,57 @@ +package com.baeldung.externalizable; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + +public class Region extends Country implements Externalizable { + + private static final long serialVersionUID = 1L; + + private String climate; + private Double population; + private Community community; + + public String getClimate() { + return climate; + } + + public void setClimate(String climate) { + this.climate = climate; + } + + public Double getPopulation() { + return population; + } + + public void setPopulation(Double population) { + this.population = population; + } + + @Override + public void writeExternal(ObjectOutput out) throws IOException { + super.writeExternal(out); + out.writeUTF(climate); + community = new Community(); + community.setId(5); + out.writeObject(community); + } + + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + super.readExternal(in); + this.climate = in.readUTF(); + community = (Community) in.readObject(); + } + + @Override + public String toString() { + return "Region = {" + + "country='" + super.toString() + '\'' + + "community='" + community.toString() + '\'' + + "climate='" + climate + '\'' + + ", population=" + population + + '}'; + } +} diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/readresolvevsreadobject/Singleton.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/readresolvevsreadobject/Singleton.java new file mode 100644 index 0000000000..91ee10dd6d --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/readresolvevsreadobject/Singleton.java @@ -0,0 +1,21 @@ +package com.baeldung.readresolvevsreadobject; + +import java.io.ObjectStreamException; +import java.io.Serializable; + +public class Singleton implements Serializable { + + private static final long serialVersionUID = 1L; + private static Singleton INSTANCE = new Singleton(); + + private Singleton() { + } + + public static Singleton getInstance() { + return INSTANCE; + } + + private Object readResolve() throws ObjectStreamException { + return INSTANCE; + } +} diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/readresolvevsreadobject/User.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/readresolvevsreadobject/User.java new file mode 100644 index 0000000000..95aac0301e --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/readresolvevsreadobject/User.java @@ -0,0 +1,59 @@ +package com.baeldung.readresolvevsreadobject; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +public class User implements Serializable { + + private static final long serialVersionUID = 3659932210257138726L; + private String userName; + private String password; + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public String toString() { + return "User [userName=" + userName + ", password=" + password + "]"; + } + + public User() { + } + + public User(String userName, String password) { + super(); + this.userName = userName; + this.password = password; + } + + private void writeObject(ObjectOutputStream oos) throws IOException { + this.password = "xyz" + password; + oos.defaultWriteObject(); + } + + private void readObject(ObjectInputStream aInputStream) + throws ClassNotFoundException, IOException { + aInputStream.defaultReadObject(); + this.password = password.substring(3); + } + + private Object readResolve() { + return this; + } + +} diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Address.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Address.java new file mode 100644 index 0000000000..055b53e70e --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Address.java @@ -0,0 +1,15 @@ +package com.baeldung.serialization; + +public class Address { + + private int houseNumber; + + public int getHouseNumber() { + return houseNumber; + } + + public void setHouseNumber(int houseNumber) { + this.houseNumber = houseNumber; + } + +} diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Customer.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Customer.java new file mode 100644 index 0000000000..51587b6c86 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Customer.java @@ -0,0 +1,35 @@ +package com.baeldung.serialization; + +import java.io.Serializable; + +public class Customer implements Serializable { + private static final long serialVersionUID = 1L; + + private long id; + private volatile String name; + private Address address; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } +} diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Employee.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Employee.java new file mode 100644 index 0000000000..0fa3ad2fc8 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Employee.java @@ -0,0 +1,44 @@ +package com.baeldung.serialization; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +public class Employee implements Serializable { + + private static final long serialVersionUID = 1L; + + private transient Address address; // not an serializable object + private Person person; + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + public Person getPerson() { + return person; + } + + public void setPerson(Person person) { + this.person = person; + } + + private void writeObject(ObjectOutputStream oos) throws IOException { + oos.defaultWriteObject(); + oos.writeObject(address.getHouseNumber()); + } + + private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { + ois.defaultReadObject(); + Integer houseNumber = (Integer) ois.readObject(); + Address a = new Address(); + a.setHouseNumber(houseNumber); + this.setAddress(a); + } + +} diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Person.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Person.java new file mode 100644 index 0000000000..4fd1a943c1 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/serialization/Person.java @@ -0,0 +1,30 @@ +package com.baeldung.serialization; +import java.io.Serializable; + +public class Person implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + + private int age; + private String name; + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/core-java-modules/core-java-serialization/src/main/java/com/baeldung/util/MySerializationUtils.java b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/util/MySerializationUtils.java new file mode 100644 index 0000000000..568a503476 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/java/com/baeldung/util/MySerializationUtils.java @@ -0,0 +1,46 @@ +package com.baeldung.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +public class MySerializationUtils { + + public static byte[] serialize(T obj) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(obj); + oos.close(); + return baos.toByteArray(); + } + + public static T deserialize(byte[] b, Class cl) throws IOException, ClassNotFoundException { + ByteArrayInputStream bais = new ByteArrayInputStream(b); + ObjectInputStream ois = new ObjectInputStream(bais); + Object o = ois.readObject(); + return cl.cast(o); + } + + public static boolean isSerializable(Class it) { + boolean serializable = it.isPrimitive() || it.isInterface() || Serializable.class.isAssignableFrom(it); + if (!serializable) { + return false; + } + Field[] declaredFields = it.getDeclaredFields(); + for (Field field : declaredFields) { + if (Modifier.isVolatile(field.getModifiers()) || Modifier.isTransient(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) { + continue; + } + Class fieldType = field.getType(); + if (!isSerializable(fieldType)) { + return false; + } + } + return true; + } +} diff --git a/core-java-modules/core-java-serialization/src/main/resources/log4j.properties b/core-java-modules/core-java-serialization/src/main/resources/log4j.properties new file mode 100644 index 0000000000..621cf01735 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/resources/log4j.properties @@ -0,0 +1,6 @@ +log4j.rootLogger=DEBUG, A1 + +log4j.appender.A1=org.apache.log4j.ConsoleAppender + +log4j.appender.A1.layout=org.apache.log4j.PatternLayout +log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n \ No newline at end of file diff --git a/core-java-modules/core-java-serialization/src/main/resources/log4j2.xml b/core-java-modules/core-java-serialization/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..a824bef9b0 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/resources/log4j2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-serialization/src/main/resources/log4jstructuraldp.properties b/core-java-modules/core-java-serialization/src/main/resources/log4jstructuraldp.properties new file mode 100644 index 0000000000..5bc2bfe4b9 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/resources/log4jstructuraldp.properties @@ -0,0 +1,9 @@ + +# Root logger +log4j.rootLogger=INFO, file, stdout + +# Write to console +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n \ No newline at end of file diff --git a/core-java-modules/core-java-serialization/src/main/resources/logback.xml b/core-java-modules/core-java-serialization/src/main/resources/logback.xml new file mode 100644 index 0000000000..56af2d397e --- /dev/null +++ b/core-java-modules/core-java-serialization/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-serialization/src/test/java/com/baeldung/deserialization/DeserializationUnitTest.java b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/deserialization/DeserializationUnitTest.java new file mode 100644 index 0000000000..89a603a298 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/deserialization/DeserializationUnitTest.java @@ -0,0 +1,69 @@ +package com.baeldung.deserialization; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.InvalidClassException; + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +public class DeserializationUnitTest { + + private static final String serializedObj = "rO0ABXNyACljb20uYmFlbGR1bmcuZGVzZXJpYWxpemF0aW9uLkFwcGxlUHJvZHVjdAAAAAAAdMuxAgADTAANaGVhZHBob25lUG9ydHQAEkxqYXZhL2xhbmcvU3RyaW5nO0wADWxpZ2h0bmluZ1BvcnRxAH4AAUwAD3RodW5kZXJib2x0UG9ydHEAfgABeHB0ABFoZWFkcGhvbmVQb3J0MjAyMHQAEWxpZ2h0bmluZ1BvcnQyMDIwdAATdGh1bmRlcmJvbHRQb3J0MjAyMA"; + + private static long userDefinedSerialVersionUID = 1234567L; + + /** + * Tests the deserialization of the original "AppleProduct" (no exceptions are thrown) + * @throws ClassNotFoundException + * @throws IOException + */ + @Test + public void testDeserializeObj_compatible() throws IOException, ClassNotFoundException { + + assertEquals(userDefinedSerialVersionUID, AppleProduct.getSerialVersionUID()); + + AppleProduct macBook = new AppleProduct(); + macBook.headphonePort = "headphonePort2020"; + macBook.thunderboltPort = "thunderboltPort2020"; + macBook.lightningPort = "lightningPort2020"; + + // serializes the "AppleProduct" object + String serializedProduct = SerializationUtility.serializeObjectToString(macBook); + + // deserializes the "AppleProduct" object + AppleProduct deserializedProduct = (AppleProduct) DeserializationUtility.deSerializeObjectFromString(serializedProduct); + + assertTrue(deserializedProduct.headphonePort.equalsIgnoreCase(macBook.headphonePort)); + assertTrue(deserializedProduct.thunderboltPort.equalsIgnoreCase(macBook.thunderboltPort)); + assertTrue(deserializedProduct.lightningPort.equalsIgnoreCase(macBook.lightningPort)); + + } + + /** + * Tests the deserialization of the modified (non-compatible) "AppleProduct". + * The test should result in an InvalidClassException being thrown. + * + * Note: to run this test: + * 1. Modify the value of the serialVersionUID identifier in AppleProduct.java + * 2. Remove the @Ignore annotation + * 3. Run the test individually (do not run the entire set of tests) + * 4. Revert the changes made in 1 & 2 (so that you're able to re-run the tests successfully) + * + * @throws ClassNotFoundException + * @throws IOException + */ + @Ignore + @Test(expected = InvalidClassException.class) + public void testDeserializeObj_incompatible() throws ClassNotFoundException, IOException { + + assertNotEquals(userDefinedSerialVersionUID, AppleProduct.getSerialVersionUID()); + // attempts to deserialize the "AppleProduct" object + DeserializationUtility.deSerializeObjectFromString(serializedObj); + } + +} diff --git a/core-java-modules/core-java-serialization/src/test/java/com/baeldung/externalizable/ExternalizableUnitTest.java b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/externalizable/ExternalizableUnitTest.java new file mode 100644 index 0000000000..9012928d92 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/externalizable/ExternalizableUnitTest.java @@ -0,0 +1,86 @@ +package com.baeldung.externalizable; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.*; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class ExternalizableUnitTest { + + private final static String OUTPUT_FILE_NAME = "externalizable.txt"; + + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + + private File outputFile; + + @Before + public void setUp() throws Exception { + outputFile = tempFolder.newFile(OUTPUT_FILE_NAME); + } + + @Test + public void whenSerializing_thenUseExternalizable() throws IOException, ClassNotFoundException { + + Country c = new Country(); + c.setCapital("Yerevan"); + c.setCode(374); + c.setName("Armenia"); + + FileOutputStream fileOutputStream = new FileOutputStream(outputFile); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); + c.writeExternal(objectOutputStream); + + objectOutputStream.flush(); + objectOutputStream.close(); + fileOutputStream.close(); + + FileInputStream fileInputStream = new FileInputStream(outputFile); + ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); + + Country c2 = new Country(); + c2.readExternal(objectInputStream); + + objectInputStream.close(); + fileInputStream.close(); + + assertEquals(c2.getCode(), c.getCode()); + assertEquals(c2.getName(), c.getName()); + } + + @Test + public void whenInheritanceSerialization_then_UseExternalizable() throws IOException, ClassNotFoundException { + + Region r = new Region(); + r.setCapital("Yerevan"); + r.setCode(374); + r.setName("Armenia"); + r.setClimate("Mediterranean"); + r.setPopulation(120.000); + + FileOutputStream fileOutputStream = new FileOutputStream(outputFile); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); + r.writeExternal(objectOutputStream); + + objectOutputStream.flush(); + objectOutputStream.close(); + fileOutputStream.close(); + + FileInputStream fileInputStream = new FileInputStream(outputFile); + ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); + + Region r2 = new Region(); + r2.readExternal(objectInputStream); + + objectInputStream.close(); + fileInputStream.close(); + + assertNull(r2.getPopulation()); + } +} diff --git a/core-java-modules/core-java-serialization/src/test/java/com/baeldung/readresolvevsreadobject/SingletonUnitTest.java b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/readresolvevsreadobject/SingletonUnitTest.java new file mode 100644 index 0000000000..3d233327e3 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/readresolvevsreadobject/SingletonUnitTest.java @@ -0,0 +1,70 @@ +package com.baeldung.readresolvevsreadobject; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.junit.After; +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +public class SingletonUnitTest { + + private static final String SINGLETON_SER = "singleton.ser"; + + @After + public void tearDown() { + final File file = new File(SINGLETON_SER); + if (file.exists()) { + file.deleteOnExit(); + } + } + + @Test + public void testSingletonObj_withNoReadResolve() throws ClassNotFoundException, IOException { + // Serialization + FileOutputStream fos = new FileOutputStream(SINGLETON_SER); + ObjectOutputStream oos = new ObjectOutputStream(fos); + Singleton actualSingletonObject = Singleton.getInstance(); + oos.writeObject(actualSingletonObject); + + // Deserialization + Singleton deserializedSingletonObject = null; + FileInputStream fis = new FileInputStream(SINGLETON_SER); + ObjectInputStream ois = new ObjectInputStream(fis); + deserializedSingletonObject = (Singleton) ois.readObject(); + // remove readResolve() from Singleton class and uncomment this to test. + //assertNotEquals(actualSingletonObject.hashCode(), deserializedSingletonObject.hashCode()); + + fos.close(); + oos.close(); + fis.close(); + ois.close(); + } + + @Test + public void testSingletonObj_withCustomReadResolve() + throws ClassNotFoundException, IOException { + // Serialization + FileOutputStream fos = new FileOutputStream(SINGLETON_SER); + ObjectOutputStream oos = new ObjectOutputStream(fos); + Singleton actualSingletonObject = Singleton.getInstance(); + oos.writeObject(actualSingletonObject); + + // Deserialization + Singleton deserializedSingletonObject; + FileInputStream fis = new FileInputStream(SINGLETON_SER); + ObjectInputStream ois = new ObjectInputStream(fis); + deserializedSingletonObject = (Singleton) ois.readObject(); + assertEquals(actualSingletonObject.hashCode(), deserializedSingletonObject.hashCode()); + + fos.close(); + oos.close(); + fis.close(); + ois.close(); + } +} diff --git a/core-java-modules/core-java-serialization/src/test/java/com/baeldung/readresolvevsreadobject/UserUnitTest.java b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/readresolvevsreadobject/UserUnitTest.java new file mode 100644 index 0000000000..cd07fd2bc7 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/readresolvevsreadobject/UserUnitTest.java @@ -0,0 +1,74 @@ +package com.baeldung.readresolvevsreadobject; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.junit.After; +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +public class UserUnitTest { + + private static final String USER_SER = "user.ser"; + + @After + public void tearDown() { + final File file = new File(USER_SER); + if (file.exists()) { + file.deleteOnExit(); + } + } + + @Test + public void testDeserializeObj_withOverriddenReadObject() throws ClassNotFoundException, IOException { + // Serialization + FileOutputStream fos = new FileOutputStream(USER_SER); + ObjectOutputStream oos = new ObjectOutputStream(fos); + User acutalObject = new User("Sachin", "Kumar"); + oos.writeObject(acutalObject); + + // Deserialization + User deserializedUser; + FileInputStream fis = new FileInputStream(USER_SER); + ObjectInputStream ois = new ObjectInputStream(fis); + deserializedUser = (User) ois.readObject(); + assertNotEquals(deserializedUser.hashCode(), acutalObject.hashCode()); + assertEquals(deserializedUser.getUserName(), "Sachin"); + assertEquals(deserializedUser.getPassword(), "Kumar"); + + fos.close(); + oos.close(); + fis.close(); + ois.close(); + } + + @Test + public void testDeserializeObj_withDefaultReadObject() + throws ClassNotFoundException, IOException { + // Serialization + FileOutputStream fos = new FileOutputStream(USER_SER); + ObjectOutputStream oos = new ObjectOutputStream(fos); + User acutalObject = new User("Sachin", "Kumar"); + oos.writeObject(acutalObject); + + // Deserialization + User deserializedUser; + FileInputStream fis = new FileInputStream(USER_SER); + ObjectInputStream ois = new ObjectInputStream(fis); + deserializedUser = (User) ois.readObject(); + assertNotEquals(deserializedUser.hashCode(), acutalObject.hashCode()); + assertEquals(deserializedUser.getUserName(), "Sachin"); + // remove readObject() from User class and uncomment this to test. + //assertEquals(deserializedUser.getPassword(), "xyzKumar"); + + fos.close(); + oos.close(); + fis.close(); + ois.close(); + } +} diff --git a/core-java-modules/core-java-serialization/src/test/java/com/baeldung/serialization/PersonUnitTest.java b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/serialization/PersonUnitTest.java new file mode 100644 index 0000000000..47dc0b9293 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/serialization/PersonUnitTest.java @@ -0,0 +1,82 @@ +package com.baeldung.serialization; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class PersonUnitTest { + + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + + private File outputFile; + + private File outputFile2; + + @Before + public void setUp() throws Exception { + outputFile = tempFolder.newFile("yourfile.txt"); + outputFile2 = tempFolder.newFile("yourfile2.txt"); + } + + @Test + public void whenSerializingAndDeserializing_ThenObjectIsTheSame() throws IOException, ClassNotFoundException { + Person p = new Person(); + p.setAge(20); + p.setName("Joe"); + + FileOutputStream fileOutputStream = new FileOutputStream(outputFile); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); + objectOutputStream.writeObject(p); + objectOutputStream.flush(); + objectOutputStream.close(); + + FileInputStream fileInputStream = new FileInputStream(outputFile); + ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); + Person p2 = (Person) objectInputStream.readObject(); + objectInputStream.close(); + + assertEquals(p2.getAge(), p.getAge()); + assertEquals(p2.getName(), p.getName()); + } + + @Test + public void whenCustomSerializingAndDeserializing_ThenObjectIsTheSame() throws IOException, ClassNotFoundException { + Person p = new Person(); + p.setAge(20); + p.setName("Joe"); + + Address a = new Address(); + a.setHouseNumber(1); + + Employee e = new Employee(); + e.setPerson(p); + e.setAddress(a); + + FileOutputStream fileOutputStream = new FileOutputStream(outputFile2); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); + objectOutputStream.writeObject(e); + objectOutputStream.flush(); + objectOutputStream.close(); + + FileInputStream fileInputStream = new FileInputStream(outputFile2); + ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); + Employee e2 = (Employee) objectInputStream.readObject(); + objectInputStream.close(); + + assertEquals(e2.getPerson().getAge(), e.getPerson().getAge()); + assertEquals(e2.getAddress().getHouseNumber(), (e.getAddress().getHouseNumber())); + } + +} diff --git a/core-java-modules/core-java-serialization/src/test/java/com/baeldung/serialization/SerializationUnitTest.java b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/serialization/SerializationUnitTest.java new file mode 100644 index 0000000000..a7cbc0599b --- /dev/null +++ b/core-java-modules/core-java-serialization/src/test/java/com/baeldung/serialization/SerializationUnitTest.java @@ -0,0 +1,129 @@ +package com.baeldung.serialization; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.NotSerializableException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +import org.apache.commons.lang3.SerializationUtils; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import com.baeldung.util.MySerializationUtils; +import org.junit.rules.TemporaryFolder; + +public class SerializationUnitTest { + + private final static String OUTPUT_FILE_NAME = "yourfile.txt"; + + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + + private File outputFile; + + @Before + public void setUp() throws Exception { + outputFile = tempFolder.newFile(OUTPUT_FILE_NAME); + } + + @Test(expected = NotSerializableException.class) + public void whenSerializing_ThenThrowsError() throws IOException { + Address address = new Address(); + address.setHouseNumber(10); + FileOutputStream fileOutputStream = new FileOutputStream(outputFile); + try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream)) { + objectOutputStream.writeObject(address); + } + } + + @Test + public void whenSerializingAndDeserializing_ThenObjectIsTheSame() throws IOException, ClassNotFoundException { + Person p = new Person(); + p.setAge(20); + p.setName("Joe"); + + FileOutputStream fileOutputStream = new FileOutputStream(outputFile); + try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream)) { + objectOutputStream.writeObject(p); + } + + FileInputStream fileInputStream = new FileInputStream(outputFile); + try (ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream)) { + Person p2 = (Person) objectInputStream.readObject(); + assertEquals(p2.getAge(), p.getAge()); + assertEquals(p2.getName(), p.getName()); + } + } + + @Test(expected = ClassCastException.class) + public void whenSerializingUsingApacheCommons_ThenThrowsError() { + Address address = new Address(); + address.setHouseNumber(10); + SerializationUtils.serialize((Serializable) address); + } + + @Test + public void whenSerializingAndDeserializingUsingApacheCommons_ThenObjectIsTheSame() { + Person p = new Person(); + p.setAge(20); + p.setName("Joe"); + byte[] serialize = SerializationUtils.serialize(p); + Person p2 = (Person) SerializationUtils.deserialize(serialize); + assertEquals(p2.getAge(), p.getAge()); + assertEquals(p2.getName(), p.getName()); + } + + @Test(expected = ClassCastException.class) + public void whenSerializingUsingSpringSerializationUtils_ThenThrowsError() { + Address address = new Address(); + address.setHouseNumber(10); + org.springframework.util.SerializationUtils.serialize((Serializable) address); + } + + @Test + public void whenSerializingAndDeserializingUsingSpringSerializationUtils_ThenObjectIsTheSame() { + Person p = new Person(); + p.setAge(20); + p.setName("Joe"); + byte[] serialize = org.springframework.util.SerializationUtils.serialize(p); + Person p2 = (Person) org.springframework.util.SerializationUtils.deserialize(serialize); + assertEquals(p2.getAge(), p.getAge()); + assertEquals(p2.getName(), p.getName()); + } + + @Test(expected = ClassCastException.class) + public void whenSerializingUsingCustomSerializationUtils_ThenThrowsError() throws IOException { + Address address = new Address(); + address.setHouseNumber(10); + MySerializationUtils.serialize((Serializable) address); + } + + @Test + public void whenSerializingAndDeserializingUsingCustomSerializationUtils_ThenObjectIsTheSame() throws IOException, ClassNotFoundException { + Person p = new Person(); + p.setAge(20); + p.setName("Joe"); + byte[] serialize = MySerializationUtils.serialize(p); + Person p2 = MySerializationUtils.deserialize(serialize, Person.class); + assertEquals(p2.getAge(), p.getAge()); + assertEquals(p2.getName(), p.getName()); + } + + @Test + public void whenSerializingUsingCustomSerializationUtils_ThanOk() { + assertFalse(MySerializationUtils.isSerializable(Address.class)); + assertTrue(MySerializationUtils.isSerializable(Person.class)); + assertTrue(MySerializationUtils.isSerializable(Integer.class)); + assertFalse(MySerializationUtils.isSerializable(Customer.class)); + assertTrue(MySerializationUtils.isSerializable(Employee.class)); + } +} diff --git a/core-java-modules/core-java-serialization/src/test/resources/log4j.properties b/core-java-modules/core-java-serialization/src/test/resources/log4j.properties new file mode 100644 index 0000000000..621cf01735 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/test/resources/log4j.properties @@ -0,0 +1,6 @@ +log4j.rootLogger=DEBUG, A1 + +log4j.appender.A1=org.apache.log4j.ConsoleAppender + +log4j.appender.A1.layout=org.apache.log4j.PatternLayout +log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n \ No newline at end of file diff --git a/core-java-modules/core-java-serialization/src/test/resources/log4j2.xml b/core-java-modules/core-java-serialization/src/test/resources/log4j2.xml new file mode 100644 index 0000000000..a824bef9b0 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/test/resources/log4j2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-serialization/src/test/resources/log4jstructuraldp.properties b/core-java-modules/core-java-serialization/src/test/resources/log4jstructuraldp.properties new file mode 100644 index 0000000000..5bc2bfe4b9 --- /dev/null +++ b/core-java-modules/core-java-serialization/src/test/resources/log4jstructuraldp.properties @@ -0,0 +1,9 @@ + +# Root logger +log4j.rootLogger=INFO, file, stdout + +# Write to console +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n \ No newline at end of file diff --git a/core-java-modules/core-java-serialization/src/test/resources/logback.xml b/core-java-modules/core-java-serialization/src/test/resources/logback.xml new file mode 100644 index 0000000000..56af2d397e --- /dev/null +++ b/core-java-modules/core-java-serialization/src/test/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file