diff --git a/experimental/model/pom.xml b/experimental/model/pom.xml
index 6777d9e2b..ca71d249a 100644
--- a/experimental/model/pom.xml
+++ b/experimental/model/pom.xml
@@ -8,9 +8,21 @@
serverlessworkflow-experimental-modelServerless Workflow :: Experimental :: Model
-
- io.serverlessworkflow
- serverlessworkflow-impl-core
-
+
+ io.serverlessworkflow
+ serverlessworkflow-impl-core
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+
+
+ org.assertj
+ assertj-core
+
+
+ ch.qos.logback
+ logback-classic
+
\ No newline at end of file
diff --git a/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/JavaModel.java b/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/JavaModel.java
index a0a13c0f4..506663b62 100644
--- a/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/JavaModel.java
+++ b/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/JavaModel.java
@@ -22,6 +22,7 @@
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
@@ -104,4 +105,18 @@ protected Optional convert(Class clazz) {
? Optional.of(clazz.cast(object))
: Optional.empty();
}
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(object);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ JavaModel other = (JavaModel) obj;
+ return Objects.equals(object, other.object);
+ }
}
diff --git a/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/JavaModelMarshaller.java b/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/JavaModelMarshaller.java
new file mode 100644
index 000000000..bf279f8bf
--- /dev/null
+++ b/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/JavaModelMarshaller.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.model.func;
+
+import io.serverlessworkflow.impl.marshaller.CustomObjectMarshaller;
+import io.serverlessworkflow.impl.marshaller.WorkflowInputBuffer;
+import io.serverlessworkflow.impl.marshaller.WorkflowOutputBuffer;
+
+public class JavaModelMarshaller implements CustomObjectMarshaller {
+
+ @Override
+ public void write(WorkflowOutputBuffer buffer, JavaModel object) {
+ buffer.writeObject(object.asJavaObject());
+ }
+
+ @Override
+ public JavaModel read(WorkflowInputBuffer buffer, Class extends JavaModel> clazz) {
+ return new JavaModel(buffer.readObject());
+ }
+
+ @Override
+ public Class getObjectClass() {
+ return JavaModel.class;
+ }
+
+ @Override
+ public int priority() {
+ return Integer.MAX_VALUE;
+ }
+}
diff --git a/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/SerializableObjectMarshaller.java b/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/SerializableObjectMarshaller.java
new file mode 100644
index 000000000..33eeeea8c
--- /dev/null
+++ b/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/SerializableObjectMarshaller.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.model.func;
+
+import io.serverlessworkflow.impl.marshaller.CustomObjectMarshaller;
+import io.serverlessworkflow.impl.marshaller.WorkflowInputBuffer;
+import io.serverlessworkflow.impl.marshaller.WorkflowOutputBuffer;
+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.io.UncheckedIOException;
+
+public class SerializableObjectMarshaller implements CustomObjectMarshaller {
+
+ @Override
+ public void write(WorkflowOutputBuffer buffer, Serializable object) {
+ try (ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+ ObjectOutputStream out = new ObjectOutputStream(bytesOut)) {
+ out.writeObject(object);
+ buffer.writeBytes(bytesOut.toByteArray());
+ } catch (IOException io) {
+ throw new UncheckedIOException(io);
+ }
+ }
+
+ @Override
+ public Serializable read(WorkflowInputBuffer buffer, Class extends Serializable> objectClass) {
+ try (ByteArrayInputStream bytesIn = new ByteArrayInputStream(buffer.readBytes());
+ ObjectInputStream in = new ObjectInputStream(bytesIn)) {
+ return objectClass.cast(in.readObject());
+ } catch (IOException io) {
+ throw new UncheckedIOException(io);
+ } catch (ClassNotFoundException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ @Override
+ public Class getObjectClass() {
+ return Serializable.class;
+ }
+
+ @Override
+ public int priority() {
+ return Integer.MAX_VALUE;
+ }
+}
diff --git a/experimental/model/src/main/resources/META-INF/services/io.serverlessworkflow.impl.marshaller.CustomObjectMarshaller b/experimental/model/src/main/resources/META-INF/services/io.serverlessworkflow.impl.marshaller.CustomObjectMarshaller
new file mode 100644
index 000000000..a3fee7dc1
--- /dev/null
+++ b/experimental/model/src/main/resources/META-INF/services/io.serverlessworkflow.impl.marshaller.CustomObjectMarshaller
@@ -0,0 +1,2 @@
+io.serverlessworkflow.impl.model.func.JavaModelMarshaller
+io.serverlessworkflow.impl.model.func.SerializableObjectMarshaller
\ No newline at end of file
diff --git a/experimental/model/src/test/java/io/serverlessworkflow/impl/model/func/Address.java b/experimental/model/src/test/java/io/serverlessworkflow/impl/model/func/Address.java
new file mode 100644
index 000000000..37a141ff8
--- /dev/null
+++ b/experimental/model/src/test/java/io/serverlessworkflow/impl/model/func/Address.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.model.func;
+
+import java.io.Serializable;
+
+record Address(String street, int number) implements Serializable {}
diff --git a/experimental/model/src/test/java/io/serverlessworkflow/impl/model/func/JavaModelSerializationTest.java b/experimental/model/src/test/java/io/serverlessworkflow/impl/model/func/JavaModelSerializationTest.java
new file mode 100644
index 000000000..a42e0dab8
--- /dev/null
+++ b/experimental/model/src/test/java/io/serverlessworkflow/impl/model/func/JavaModelSerializationTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.model.func;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import io.serverlessworkflow.impl.marshaller.DefaultBufferFactory;
+import io.serverlessworkflow.impl.marshaller.WorkflowBufferFactory;
+import io.serverlessworkflow.impl.marshaller.WorkflowInputBuffer;
+import io.serverlessworkflow.impl.marshaller.WorkflowOutputBuffer;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import org.junit.jupiter.api.Test;
+
+class JavaModelSerializationTest {
+
+ @Test
+ void testSerializableJavaModel() throws IOException {
+ testMarshallUnMarshall(
+ new JavaModel(new Person("Pepe Gotera", 32, new Address("Rue del Percebe", 13))));
+ }
+
+ private void testMarshallUnMarshall(Object object) {
+ WorkflowBufferFactory factory = DefaultBufferFactory.factory();
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ try (WorkflowOutputBuffer writer = factory.output(output)) {
+ writer.writeObject(object);
+ }
+ ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
+ try (WorkflowInputBuffer reader = factory.input(input)) {
+ assertThat(reader.readObject()).isEqualTo(object);
+ }
+ }
+}
diff --git a/experimental/model/src/test/java/io/serverlessworkflow/impl/model/func/Person.java b/experimental/model/src/test/java/io/serverlessworkflow/impl/model/func/Person.java
new file mode 100644
index 000000000..de7dba780
--- /dev/null
+++ b/experimental/model/src/test/java/io/serverlessworkflow/impl/model/func/Person.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.model.func;
+
+import java.io.Serializable;
+
+record Person(String name, int age, Address address) implements Serializable {}
diff --git a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/AbstractInputBuffer.java b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/AbstractInputBuffer.java
similarity index 92%
rename from impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/AbstractInputBuffer.java
rename to impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/AbstractInputBuffer.java
index b79717177..5b3d66276 100644
--- a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/AbstractInputBuffer.java
+++ b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/AbstractInputBuffer.java
@@ -131,10 +131,7 @@ protected Class> loadClass(String className) throws ClassNotFoundException {
protected Object readCustomObject() {
Class> objectClass = readClass();
- return customMarshallers.stream()
- .filter(m -> m.getObjectClass().isAssignableFrom(objectClass))
- .findFirst()
- .map(m -> m.read(this))
- .orElseThrow(() -> new IllegalArgumentException("Unsupported type " + objectClass));
+ return MarshallingUtils.getCustomMarshaller(customMarshallers, objectClass)
+ .read(this, objectClass);
}
}
diff --git a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/AbstractOutputBuffer.java b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/AbstractOutputBuffer.java
similarity index 91%
rename from impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/AbstractOutputBuffer.java
rename to impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/AbstractOutputBuffer.java
index fb002800a..17612b5a1 100644
--- a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/AbstractOutputBuffer.java
+++ b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/AbstractOutputBuffer.java
@@ -73,7 +73,7 @@ public WorkflowOutputBuffer writeObject(Object object) {
writeLong(number);
} else if (object instanceof Byte number) {
writeType(Type.BYTE);
- writeLong(number);
+ writeByte(number);
} else if (object instanceof Float number) {
writeType(Type.FLOAT);
writeFloat(number);
@@ -109,14 +109,11 @@ protected void writeClass(Class> objectClass) {
writeString(objectClass.getCanonicalName());
}
+ @SuppressWarnings({"rawtypes", "unchecked"})
protected void writeCustomObject(Object object) {
CustomObjectMarshaller marshaller =
- customMarshallers.stream()
- .filter(m -> m.getObjectClass().isAssignableFrom(object.getClass()))
- .findFirst()
- .orElseThrow(
- () -> new IllegalArgumentException("Unsupported type " + object.getClass()));
- writeClass(marshaller.getObjectClass());
+ MarshallingUtils.getCustomMarshaller(customMarshallers, object.getClass());
+ writeClass(object.getClass());
marshaller.write(this, marshaller.getObjectClass().cast(object));
}
diff --git a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/CustomObjectMarshaller.java b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/CustomObjectMarshaller.java
similarity index 93%
rename from impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/CustomObjectMarshaller.java
rename to impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/CustomObjectMarshaller.java
index 23fbe1bb1..23e10287b 100644
--- a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/CustomObjectMarshaller.java
+++ b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/CustomObjectMarshaller.java
@@ -20,7 +20,7 @@
public interface CustomObjectMarshaller extends ServicePriority {
void write(WorkflowOutputBuffer buffer, T object);
- T read(WorkflowInputBuffer buffer);
+ T read(WorkflowInputBuffer buffer, Class extends T> clazz);
Class getObjectClass();
}
diff --git a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/DefaultBufferFactory.java b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/DefaultBufferFactory.java
similarity index 98%
rename from impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/DefaultBufferFactory.java
rename to impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/DefaultBufferFactory.java
index ba3d2cc86..5fbc7efa3 100644
--- a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/DefaultBufferFactory.java
+++ b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/DefaultBufferFactory.java
@@ -29,6 +29,7 @@ private static class DefaultBufferFactoryHolder {
new DefaultBufferFactory(
ServiceLoader.load(CustomObjectMarshaller.class).stream()
.map(ServiceLoader.Provider::get)
+ .sorted()
.toList());
}
diff --git a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/DefaultInputBuffer.java b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/DefaultInputBuffer.java
similarity index 100%
rename from impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/DefaultInputBuffer.java
rename to impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/DefaultInputBuffer.java
diff --git a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/DefaultOutputBuffer.java b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/DefaultOutputBuffer.java
similarity index 100%
rename from impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/DefaultOutputBuffer.java
rename to impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/DefaultOutputBuffer.java
diff --git a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/MarshallingUtils.java b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/MarshallingUtils.java
similarity index 73%
rename from impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/MarshallingUtils.java
rename to impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/MarshallingUtils.java
index e82333951..d71deb5ab 100644
--- a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/MarshallingUtils.java
+++ b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/MarshallingUtils.java
@@ -19,6 +19,7 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.time.Instant;
+import java.util.Collection;
import java.util.function.BiConsumer;
import java.util.function.Function;
@@ -95,4 +96,32 @@ private static T readValue(
return valueConsumer.apply(buffer);
}
}
+
+ /**
+ * Retrieve more proper marshaler for the given class. Collection is assumed to be already sorted
+ * by priority. No matter which priority is given, if the object class is equal to the marshaler
+ * class, it should have precedence over an object class which is assignable to the marshaler
+ * class.
+ *
+ * @param marshallers Priority Sorted collection of marshalers available on classpath
+ * @param clazz The class of the object being marshaled
+ * @return The most suitable marshaler for that object class
+ * @throws IllegalArgumentException if no marshaler is found for that object class
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ public static CustomObjectMarshaller getCustomMarshaller(
+ Collection marshallers, Class clazz) {
+ CustomObjectMarshaller assignable = null;
+ for (CustomObjectMarshaller marshaller : marshallers) {
+ if (marshaller.getObjectClass().equals(clazz)) {
+ return marshaller;
+ } else if (marshaller.getObjectClass().isAssignableFrom(clazz) && assignable == null) {
+ assignable = marshaller;
+ }
+ }
+ if (assignable == null) {
+ throw new IllegalArgumentException("Cannot find proper marshaler for class " + clazz);
+ }
+ return assignable;
+ }
}
diff --git a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/TaskStatus.java b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/TaskStatus.java
similarity index 100%
rename from impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/TaskStatus.java
rename to impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/TaskStatus.java
diff --git a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/Type.java b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/Type.java
similarity index 100%
rename from impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/Type.java
rename to impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/Type.java
diff --git a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/WorkflowBufferFactory.java b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/WorkflowBufferFactory.java
similarity index 100%
rename from impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/WorkflowBufferFactory.java
rename to impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/WorkflowBufferFactory.java
diff --git a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/WorkflowInputBuffer.java b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/WorkflowInputBuffer.java
similarity index 100%
rename from impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/WorkflowInputBuffer.java
rename to impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/WorkflowInputBuffer.java
diff --git a/impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/WorkflowOutputBuffer.java b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/WorkflowOutputBuffer.java
similarity index 100%
rename from impl/persistence/api/src/main/java/io/serverlessworkflow/impl/marshaller/WorkflowOutputBuffer.java
rename to impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/WorkflowOutputBuffer.java
diff --git a/impl/core/src/test/java/io/serverlessworkflow/impl/marshaller/Employee.java b/impl/core/src/test/java/io/serverlessworkflow/impl/marshaller/Employee.java
new file mode 100644
index 000000000..1a8d7455b
--- /dev/null
+++ b/impl/core/src/test/java/io/serverlessworkflow/impl/marshaller/Employee.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.marshaller;
+
+class Employee extends Person {}
diff --git a/impl/core/src/test/java/io/serverlessworkflow/impl/marshaller/MarshallingUtilsTest.java b/impl/core/src/test/java/io/serverlessworkflow/impl/marshaller/MarshallingUtilsTest.java
new file mode 100644
index 000000000..51ade121f
--- /dev/null
+++ b/impl/core/src/test/java/io/serverlessworkflow/impl/marshaller/MarshallingUtilsTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.marshaller;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+class MarshallingUtilsTest {
+
+ @Test
+ void testCustomMarshallers() {
+ CustomObjectMarshaller personMarshaller = Mockito.spy(CustomObjectMarshaller.class);
+ Mockito.when(personMarshaller.priority()).thenReturn(1);
+ Mockito.when(personMarshaller.getObjectClass()).thenReturn(Person.class);
+ CustomObjectMarshaller employeeMarshaller = Mockito.spy(CustomObjectMarshaller.class);
+ Mockito.when(employeeMarshaller.priority()).thenReturn(2);
+ Mockito.when(employeeMarshaller.getObjectClass()).thenReturn(Employee.class);
+ CustomObjectMarshaller objectMarshaller = Mockito.spy(CustomObjectMarshaller.class);
+ Mockito.when(objectMarshaller.priority()).thenReturn(3);
+ Mockito.when(objectMarshaller.getObjectClass()).thenReturn(Object.class);
+ Object employee = new Employee();
+ Object person = new Person();
+ Object other = new byte[2];
+
+ List marshallers =
+ Stream.of(objectMarshaller, employeeMarshaller, personMarshaller)
+ .sorted()
+ .collect(Collectors.toList());
+ assertThat(marshallers).containsExactly(personMarshaller, employeeMarshaller, objectMarshaller);
+ assertThat(MarshallingUtils.getCustomMarshaller(marshallers, employee.getClass()))
+ .isEqualTo(employeeMarshaller);
+ assertThat(MarshallingUtils.getCustomMarshaller(marshallers, person.getClass()))
+ .isEqualTo(personMarshaller);
+ assertThat(MarshallingUtils.getCustomMarshaller(marshallers, other.getClass()))
+ .isEqualTo(objectMarshaller);
+ }
+}
diff --git a/impl/core/src/test/java/io/serverlessworkflow/impl/marshaller/Person.java b/impl/core/src/test/java/io/serverlessworkflow/impl/marshaller/Person.java
new file mode 100644
index 000000000..a618f9e26
--- /dev/null
+++ b/impl/core/src/test/java/io/serverlessworkflow/impl/marshaller/Person.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.marshaller;
+
+class Person {}
diff --git a/impl/persistence/jackson-marshaller/src/main/java/io/serverlessworkflow/impl/marshaller/jackson/JacksonModelMarshaller.java b/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/AbstractJacksonMarshaller.java
similarity index 69%
rename from impl/persistence/jackson-marshaller/src/main/java/io/serverlessworkflow/impl/marshaller/jackson/JacksonModelMarshaller.java
rename to impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/AbstractJacksonMarshaller.java
index ba467b766..47f73d25d 100644
--- a/impl/persistence/jackson-marshaller/src/main/java/io/serverlessworkflow/impl/marshaller/jackson/JacksonModelMarshaller.java
+++ b/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/AbstractJacksonMarshaller.java
@@ -13,21 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.serverlessworkflow.impl.marshaller.jackson;
+package io.serverlessworkflow.impl.model.jackson;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.serverlessworkflow.impl.jackson.JsonUtils;
import io.serverlessworkflow.impl.marshaller.CustomObjectMarshaller;
import io.serverlessworkflow.impl.marshaller.WorkflowInputBuffer;
import io.serverlessworkflow.impl.marshaller.WorkflowOutputBuffer;
-import io.serverlessworkflow.impl.model.jackson.JacksonModel;
import java.io.IOException;
import java.io.UncheckedIOException;
-public class JacksonModelMarshaller implements CustomObjectMarshaller {
+abstract class AbstractJacksonMarshaller implements CustomObjectMarshaller {
@Override
- public void write(WorkflowOutputBuffer buffer, JacksonModel object) {
+ public void write(WorkflowOutputBuffer buffer, T object) {
try {
buffer.writeBytes(JsonUtils.mapper().writeValueAsBytes(object));
} catch (JsonProcessingException e) {
@@ -36,17 +35,11 @@ public void write(WorkflowOutputBuffer buffer, JacksonModel object) {
}
@Override
- public JacksonModel read(WorkflowInputBuffer buffer) {
+ public T read(WorkflowInputBuffer buffer, Class extends T> clazz) {
try {
- JacksonModel model = JsonUtils.mapper().readValue(buffer.readBytes(), JacksonModel.class);
- return model == null ? JacksonModel.NULL : model;
+ return JsonUtils.mapper().readValue(buffer.readBytes(), clazz);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
-
- @Override
- public Class getObjectClass() {
- return JacksonModel.class;
- }
}
diff --git a/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModel.java b/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModel.java
index e30581711..aae12ba9b 100644
--- a/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModel.java
+++ b/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModel.java
@@ -30,6 +30,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
@JsonSerialize(using = JacksonModelSerializer.class)
@@ -131,4 +132,18 @@ protected Optional convert(Class clazz) {
? Optional.of(clazz.cast(node))
: Optional.of(JsonUtils.mapper().convertValue(node, clazz));
}
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(node);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ JacksonModel other = (JacksonModel) obj;
+ return Objects.equals(node, other.node);
+ }
}
diff --git a/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModelMarshaller.java b/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModelMarshaller.java
new file mode 100644
index 000000000..ca95e82fb
--- /dev/null
+++ b/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModelMarshaller.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.model.jackson;
+
+import io.serverlessworkflow.impl.marshaller.WorkflowInputBuffer;
+
+public class JacksonModelMarshaller extends AbstractJacksonMarshaller {
+
+ @Override
+ public JacksonModel read(WorkflowInputBuffer buffer, Class extends JacksonModel> clazz) {
+ JacksonModel model = super.read(buffer, clazz);
+ return model == null ? JacksonModel.NULL : model;
+ }
+
+ @Override
+ public Class getObjectClass() {
+ return JacksonModel.class;
+ }
+}
diff --git a/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonObjectMarshaller.java b/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonObjectMarshaller.java
new file mode 100644
index 000000000..1f406f804
--- /dev/null
+++ b/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonObjectMarshaller.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.serverlessworkflow.impl.model.jackson;
+
+public class JacksonObjectMarshaller extends AbstractJacksonMarshaller