You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2021/03/01 08:52:36 UTC

[isis] branch master updated: ISIS-2554: TypeIdentifier: use SerializationProxy instead

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new 94de9df  ISIS-2554: TypeIdentifier: use SerializationProxy instead
94de9df is described below

commit 94de9dfb128e8441a7d51822fe0caf1d7c75c7da
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Mar 1 09:52:24 2021 +0100

    ISIS-2554: TypeIdentifier: use SerializationProxy instead
    
    adds serialization tests
    
    also make SerializationTester more broadly available
---
 .../org/apache/isis/applib/id/TypeIdentifier.java  | 49 +++++++++++---------
 .../apache/isis/applib/id/TypeIdentifierTest.java  | 52 ++++++++++++++++++++++
 .../internal/testing/_SerializationTester.java}    | 42 +++++++----------
 .../apache/isis/commons/collections/CanTest.java   | 12 ++---
 .../isis/commons/collections/CanVectorTest.java    |  8 ++--
 5 files changed, 108 insertions(+), 55 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/id/TypeIdentifier.java b/api/applib/src/main/java/org/apache/isis/applib/id/TypeIdentifier.java
index 8c2f2d4..b24bab1 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/id/TypeIdentifier.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/id/TypeIdentifier.java
@@ -18,10 +18,9 @@
  */
 package org.apache.isis.applib.id;
 
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
 import java.util.Objects;
 import java.util.function.Supplier;
 
@@ -45,16 +44,15 @@ import lombok.val;
 public final class TypeIdentifier 
 implements 
     Comparable<TypeIdentifier>,
-    Externalizable {
+    Serializable {
+    
+    private static final long serialVersionUID = 1L;
 
     /**
-     * Class this identifier represents.
-     * 
-     * @implNote in support of de-serialization cannot be declared final 
-     * (Java 15+ records will solve this issue)
+     * Type ({@link Class} this identifier represents.
      */
     @Getter
-    private /*final*/ Class<?> correspondingClass;
+    private final Class<?> correspondingClass;
     
     @ToString.Exclude
     private final Supplier<String> logicalNameProvider;
@@ -185,18 +183,29 @@ implements
         return _Strings.compareNullsFirst(correspondingClass.getCanonicalName(), otherClassName);
     }
 
-    // -- SERIALIZATION
-    
-    @Override
-    public void writeExternal(ObjectOutput out) throws IOException {
-        out.writeObject(getCorrespondingClass());
-        out.writeUTF(getLogicalTypeName());
+    // -- SERIALIZATION PROXY
+
+    private Object writeReplace() {
+        return new SerializationProxy(this);
     }
 
-    @Override
-    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
-        this.correspondingClass = (Class<?>) in.readObject();
-        this.logicalName = in.readUTF();
+    private void readObject(ObjectInputStream stream) throws InvalidObjectException {
+        throw new InvalidObjectException("Proxy required");
+    }
+
+    private static class SerializationProxy implements Serializable {
+        private static final long serialVersionUID = 1L;
+        private final @NonNull Class<?> correspondingClass;
+        private final @NonNull String logicalTypeName;
+        
+        private SerializationProxy(TypeIdentifier typeIdentifier) {
+            this.correspondingClass = typeIdentifier.getCorrespondingClass();
+            this.logicalTypeName = typeIdentifier.getLogicalTypeName();
+        }
+
+        private Object readResolve() {
+            return TypeIdentifier.eager(correspondingClass, logicalTypeName);
+        }
     }
     
     // -- HELPER
diff --git a/api/applib/src/test/java/org/apache/isis/applib/id/TypeIdentifierTest.java b/api/applib/src/test/java/org/apache/isis/applib/id/TypeIdentifierTest.java
new file mode 100644
index 0000000..01be20d
--- /dev/null
+++ b/api/applib/src/test/java/org/apache/isis/applib/id/TypeIdentifierTest.java
@@ -0,0 +1,52 @@
+package org.apache.isis.applib.id;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.isis.applib.SomeDomainClass;
+import org.apache.isis.commons.internal.testing._SerializationTester;
+
+import lombok.val;
+
+class TypeIdentifierTest {
+
+    @BeforeEach
+    void setUp() throws Exception {
+    }
+
+    @Test
+    void eager() {
+        
+        val original = TypeIdentifier.fqcn(SomeDomainClass.class);
+        
+        _SerializationTester.assertEqualsOnRoundtrip(original);
+        
+        assertEquals(
+                original.getLogicalTypeName(),
+                SomeDomainClass.class.getName());
+        
+        assertEquals(
+                _SerializationTester.roundtrip(original).getLogicalTypeName(), 
+                original.getLogicalTypeName());
+    }
+    
+    @Test
+    void lazy() {
+        
+        val original = TypeIdentifier.lazy(SomeDomainClass.class, ()->"hello");
+        
+        _SerializationTester.assertEqualsOnRoundtrip(original);
+        
+        assertEquals(
+                original.getLogicalTypeName(),
+                "hello");
+        
+        assertEquals(
+                _SerializationTester.roundtrip(original).getLogicalTypeName(), 
+                original.getLogicalTypeName());
+    }
+
+
+}
diff --git a/commons/src/test/java/org/apache/isis/commons/SerializationTester.java b/commons/src/main/java/org/apache/isis/commons/internal/testing/_SerializationTester.java
similarity index 66%
rename from commons/src/test/java/org/apache/isis/commons/SerializationTester.java
rename to commons/src/main/java/org/apache/isis/commons/internal/testing/_SerializationTester.java
index 0a3960d..f36f913 100644
--- a/commons/src/test/java/org/apache/isis/commons/SerializationTester.java
+++ b/commons/src/main/java/org/apache/isis/commons/internal/testing/_SerializationTester.java
@@ -16,28 +16,28 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.commons;
+package org.apache.isis.commons.internal.testing;
 
 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 static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.fail;
+import org.apache.isis.commons.internal.assertions._Assert;
 
+import lombok.SneakyThrows;
 import lombok.val;
 
 /**
  * in-memory serialization round-tripping
- * @since Jul 2, 2020
+ * @since 2.0
  *
  */
-public class SerializationTester {
+public class _SerializationTester {
 
-    public static byte[] marshall(Serializable object) throws IOException {
+    @SneakyThrows
+    public static byte[] marshall(Serializable object) {
         val bos = new ByteArrayOutputStream(16*4096); // 16k initial buffer size
         val oos = new ObjectOutputStream(bos);
         oos.writeObject(object);
@@ -46,7 +46,8 @@ public class SerializationTester {
         return bos.toByteArray();
     }
 
-    public static <T> T unmarshall(byte[] input) throws IOException, ClassNotFoundException {
+    @SneakyThrows
+    public static <T> T unmarshall(byte[] input) {
         val bis = new ByteArrayInputStream(input);
         val ois = new ObjectInputStream(bis);
         @SuppressWarnings("unchecked")
@@ -55,31 +56,22 @@ public class SerializationTester {
         return t;
     }
 
-    public static <T extends Serializable> T roundtrip(T object) throws IOException, ClassNotFoundException {
+    @SneakyThrows
+    public static <T extends Serializable> T roundtrip(T object) {
         val bytes = marshall(object);
         return unmarshall(bytes);
     }
 
+    @SneakyThrows
     public static <T extends Serializable> void assertEqualsOnRoundtrip(T object) {
-        T afterRoundtrip;
-        try {
-            afterRoundtrip = roundtrip(object);
-        } catch (ClassNotFoundException | IOException e) {
-            fail(e);
-            return;
-        }
-        assertEquals(object, afterRoundtrip);
+        T afterRoundtrip = roundtrip(object);
+        _Assert.assertEquals(object, afterRoundtrip);
     }
 
+    @SneakyThrows
     public static void selftest() {
-        String afterRoundtrip;
-        try {
-            afterRoundtrip = roundtrip("Hello World!");
-        } catch (ClassNotFoundException | IOException e) {
-            fail(e);
-            return;
-        }
-        assertEquals("Hello World!", afterRoundtrip);
+        String afterRoundtrip = roundtrip("Hello World!");
+        _Assert.assertEquals("Hello World!", afterRoundtrip);
         assertEqualsOnRoundtrip("Hello World!");
     }
 
diff --git a/commons/src/test/java/org/apache/isis/commons/collections/CanTest.java b/commons/src/test/java/org/apache/isis/commons/collections/CanTest.java
index 1d5e7bb..7430eb3 100644
--- a/commons/src/test/java/org/apache/isis/commons/collections/CanTest.java
+++ b/commons/src/test/java/org/apache/isis/commons/collections/CanTest.java
@@ -27,7 +27,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import org.apache.isis.commons.SerializationTester;
+import org.apache.isis.commons.internal.testing._SerializationTester;
 
 import lombok.val;
 
@@ -35,7 +35,7 @@ class CanTest {
 
     @Test
     void tester_selftest() throws ClassNotFoundException, IOException {
-        SerializationTester.selftest();
+        _SerializationTester.selftest();
     }
     
     @Test
@@ -45,18 +45,18 @@ class CanTest {
     
     @Test
     void emptyCan_shouldBeSerializable() {
-        SerializationTester.assertEqualsOnRoundtrip(Can.empty());
-        SerializationTester.assertEqualsOnRoundtrip(Can.<String>of());
+        _SerializationTester.assertEqualsOnRoundtrip(Can.empty());
+        _SerializationTester.assertEqualsOnRoundtrip(Can.<String>of());
     }
     
     @Test
     void singletonCan_shouldBeSerializable() {
-        SerializationTester.assertEqualsOnRoundtrip(Can.<String>of("hi"));
+        _SerializationTester.assertEqualsOnRoundtrip(Can.<String>of("hi"));
     }
     
     @Test
     void multiCan_shouldBeSerializable() {
-        SerializationTester.assertEqualsOnRoundtrip(Can.<String>of("hi", "there"));
+        _SerializationTester.assertEqualsOnRoundtrip(Can.<String>of("hi", "there"));
     }
     
     // -- REVERTING
diff --git a/commons/src/test/java/org/apache/isis/commons/collections/CanVectorTest.java b/commons/src/test/java/org/apache/isis/commons/collections/CanVectorTest.java
index 459b1aa..eeaf33a 100644
--- a/commons/src/test/java/org/apache/isis/commons/collections/CanVectorTest.java
+++ b/commons/src/test/java/org/apache/isis/commons/collections/CanVectorTest.java
@@ -22,7 +22,7 @@ import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import org.apache.isis.commons.SerializationTester;
+import org.apache.isis.commons.internal.testing._SerializationTester;
 
 import lombok.val;
 
@@ -35,8 +35,8 @@ class CanVectorTest {
     
     @Test
     void emptyCanVector_shouldBeSerializable() {
-        SerializationTester.assertEqualsOnRoundtrip(CanVector.empty());
-        SerializationTester.assertEqualsOnRoundtrip(new CanVector<String>(0));
+        _SerializationTester.assertEqualsOnRoundtrip(CanVector.empty());
+        _SerializationTester.assertEqualsOnRoundtrip(new CanVector<String>(0));
     }
     
     @Test
@@ -44,7 +44,7 @@ class CanVectorTest {
         val vector = new CanVector<String>(3);
         vector.set(0, Can.<String>of("hi"));
         vector.set(1, Can.<String>of("hi", "there"));
-        SerializationTester.assertEqualsOnRoundtrip(Can.<String>of("hi"));
+        _SerializationTester.assertEqualsOnRoundtrip(Can.<String>of("hi"));
     }
 
 }