+ xmlDoc: Document
+}
+class LobSerializer
+class Plant {
+ - name: String
+ - type: String
+ name: String
+ type: String
+}
+
+Animal -[#595959,dashed]-> Plant : "«create»"
+Animal "1" *-[#595959,plain]-> "plantsEaten\n*" Plant
+App -[#595959,dashed]-> Animal : "«create»"
+App -[#595959,dashed]-> ClobSerializer : "«create»"
+App -[#595959,dashed]-> Forest : "«create»"
+App -[#595959,dashed]-> Plant : "«create»"
+BlobSerializer -[#000082,plain]-^ LobSerializer
+ClobSerializer -[#595959,dashed]-> Forest : "«create»"
+ClobSerializer -[#000082,plain]-^ LobSerializer
+Forest "1" *-[#595959,plain]-> "animals\n*" Animal
+Forest "1" *-[#595959,plain]-> "plants\n*" Plant
+LobSerializer "1" *-[#595959,plain]-> "databaseService\n1" DatabaseService
+LobSerializer -[#595959,dashed]-> DatabaseService : "«create»"
+@enduml
diff --git a/slob/pom.xml b/slob/pom.xml
new file mode 100644
index 000000000000..5f95d4c1b2c2
--- /dev/null
+++ b/slob/pom.xml
@@ -0,0 +1,78 @@
+
+
+
+
+ slob
+ 4.0.0
+
+ java-design-patterns
+ com.iluwatar
+ 1.26.0-SNAPSHOT
+
+
+
+
+
+ maven-assembly-plugin
+
+
+
+
+
+ com.iluwatar.slob.App
+
+
+
+
+
+ org.apache.maven.plugins
+
+
+
+
+
+
+ junit-jupiter-engine
+ org.junit.jupiter
+ test
+
+
+ h2
+ com.h2database
+ 2.2.220
+
+
+ lombok
+ org.projectlombok
+ provided
+
+
+
+
diff --git a/slob/src/main/java/com/iluwatar/slob/App.java b/slob/src/main/java/com/iluwatar/slob/App.java
new file mode 100644
index 000000000000..743cc8293f1f
--- /dev/null
+++ b/slob/src/main/java/com/iluwatar/slob/App.java
@@ -0,0 +1,144 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.slob;
+
+import com.iluwatar.slob.lob.Animal;
+import com.iluwatar.slob.lob.Forest;
+import com.iluwatar.slob.lob.Plant;
+import com.iluwatar.slob.serializers.BlobSerializer;
+import com.iluwatar.slob.serializers.ClobSerializer;
+import com.iluwatar.slob.serializers.LobSerializer;
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
+
+/**
+ * SLOB Application using {@link LobSerializer} and H2 DB.
+ */
+public class App {
+
+ public static final String CLOB = "CLOB";
+ private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
+
+ /**
+ * Main entry point to program.
+ * In the SLOB pattern, the object graph is serialized into a single large object (a BLOB or
+ * CLOB, for Binary Large Object or Character Large Object, respectively) and stored in the
+ * database. When the object graph needs to be retrieved, it is read from the database and
+ * deserialized back into the original object graph.
+ *
+ * A Forest is created using {@link #createForest()} with Animals and Plants along with their
+ * respective relationships.
+ *
+ * Creates a {@link LobSerializer} using the method
+ * {@link #createLobSerializer(String[])}.
+ *
+ * Once created the serializer is passed to the
+ * {@link #executeSerializer(Forest, LobSerializer)} which handles the serialization,
+ * deserialization and persisting and loading from DB.
+ *
+ * @param args if first arg is CLOB then ClobSerializer is used else BlobSerializer is used.
+ */
+ public static void main(String[] args) throws SQLException {
+ Forest forest = createForest();
+ LobSerializer serializer = createLobSerializer(args);
+ executeSerializer(forest, serializer);
+ }
+
+ /**
+ * Creates a {@link LobSerializer} on the basis of input args.
+ * If input args are not empty and the value equals {@link App#CLOB} then a
+ * {@link ClobSerializer} is created else a {@link BlobSerializer} is created.
+ *
+ * @param args if first arg is {@link App#CLOB} then ClobSerializer is instantiated else
+ * BlobSerializer is instantiated.
+ */
+ private static LobSerializer createLobSerializer(String[] args) throws SQLException {
+ LobSerializer serializer;
+ if (args.length > 0 && Objects.equals(args[0], CLOB)) {
+ serializer = new ClobSerializer();
+ } else {
+ serializer = new BlobSerializer();
+ }
+ return serializer;
+ }
+
+ /**
+ * Creates a Forest with {@link Animal} and {@link Plant} along with their respective
+ * relationships.
+ *
+ * The method creates a {@link Forest} with 2 Plants Grass and Oak of type Herb and tree
+ * respectively.
+ *
+ * It also creates 3 animals Zebra and Buffalo which eat the plant grass. Lion consumes the
+ * Zebra and the Buffalo.
+ *
+ * With the above animals and plants and their relationships a forest
+ * object is created which represents the Object Graph.
+ *
+ * @return Forest Object
+ */
+ private static Forest createForest() {
+ Plant grass = new Plant("Grass", "Herb");
+ Plant oak = new Plant("Oak", "Tree");
+
+ Animal zebra = new Animal("Zebra", Set.of(grass), Collections.emptySet());
+ Animal buffalo = new Animal("Buffalo", Set.of(grass), Collections.emptySet());
+ Animal lion = new Animal("Lion", Collections.emptySet(), Set.of(zebra, buffalo));
+
+ return new Forest("Amazon", Set.of(lion, buffalo, zebra), Set.of(grass, oak));
+ }
+
+ /**
+ * Serialize the input object using the input serializer and persist to DB. After this it loads
+ * the same object back from DB and deserializes using the same serializer.
+ *
+ * @param forest Object to Serialize and Persist
+ * @param lobSerializer Serializer to Serialize and Deserialize Object
+ */
+ private static void executeSerializer(Forest forest, LobSerializer lobSerializer) {
+ try (LobSerializer serializer = lobSerializer) {
+
+ Object serialized = serializer.serialize(forest);
+ int id = serializer.persistToDb(1, forest.getName(), serialized);
+
+ Object fromDb = serializer.loadFromDb(id, Forest.class.getSimpleName());
+ Forest forestFromDb = serializer.deSerialize(fromDb);
+
+ LOGGER.info(forestFromDb.toString());
+ } catch (SQLException | IOException | TransformerException | ParserConfigurationException
+ | SAXException
+ | ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/slob/src/main/java/com/iluwatar/slob/dbservice/DatabaseService.java b/slob/src/main/java/com/iluwatar/slob/dbservice/DatabaseService.java
new file mode 100644
index 000000000000..ea54592c99d1
--- /dev/null
+++ b/slob/src/main/java/com/iluwatar/slob/dbservice/DatabaseService.java
@@ -0,0 +1,157 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.slob.dbservice;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import javax.sql.DataSource;
+import lombok.extern.slf4j.Slf4j;
+import org.h2.jdbcx.JdbcDataSource;
+
+/**
+ * Service to handle database operations.
+ */
+@Slf4j
+public class DatabaseService {
+
+ public static final String CREATE_BINARY_SCHEMA_DDL =
+ "CREATE TABLE IF NOT EXISTS FORESTS (ID NUMBER UNIQUE, NAME VARCHAR(30),FOREST VARBINARY)";
+ public static final String CREATE_TEXT_SCHEMA_DDL =
+ "CREATE TABLE IF NOT EXISTS FORESTS (ID NUMBER UNIQUE, NAME VARCHAR(30),FOREST VARCHAR)";
+ public static final String DELETE_SCHEMA_SQL = "DROP TABLE FORESTS IF EXISTS";
+ public static final String BINARY_DATA = "BINARY";
+ private static final String DB_URL = "jdbc:h2:~/test";
+ private static final String INSERT = "insert into FORESTS (id,name, forest) values (?,?,?)";
+ private static final String SELECT = "select FOREST from FORESTS where id = ?";
+ private static final DataSource dataSource = createDataSource();
+ public String dataTypeDb;
+
+ /**
+ * Constructor initializes {@link DatabaseService#dataTypeDb}.
+ *
+ * @param dataTypeDb Type of data that is to be stored in DB can be 'TEXT' or 'BINARY'.
+ */
+ public DatabaseService(String dataTypeDb) {
+ this.dataTypeDb = dataTypeDb;
+ }
+
+ /**
+ * Initiates Data source.
+ *
+ * @return created data source
+ */
+ private static DataSource createDataSource() {
+ var dataSource = new JdbcDataSource();
+ dataSource.setURL(DB_URL);
+ return dataSource;
+ }
+
+ /**
+ * Shutdown Sequence executes Query {@link DatabaseService#DELETE_SCHEMA_SQL}.
+ *
+ * @throws SQLException if any issue occurs while executing DROP Query
+ */
+ public void shutDownService()
+ throws SQLException {
+ try (var connection = dataSource.getConnection();
+ var statement = connection.createStatement()) {
+ statement.execute(DELETE_SCHEMA_SQL);
+ }
+ }
+
+ /**
+ * Initaites startup sequence and executes the query
+ * {@link DatabaseService#CREATE_BINARY_SCHEMA_DDL} if {@link DatabaseService#dataTypeDb} is
+ * binary else will execute the query {@link DatabaseService#CREATE_TEXT_SCHEMA_DDL}.
+ *
+ * @throws SQLException if there are any issues during DDL execution
+ */
+ public void startupService()
+ throws SQLException {
+ try (var connection = dataSource.getConnection();
+ var statement = connection.createStatement()) {
+ if (dataTypeDb.equals("BINARY")) {
+ statement.execute(CREATE_BINARY_SCHEMA_DDL);
+ } else {
+ statement.execute(CREATE_TEXT_SCHEMA_DDL);
+ }
+ }
+ }
+
+ /**
+ * Executes the insert query {@link DatabaseService#INSERT}.
+ *
+ * @param id with which row is to be inserted
+ * @param name name to be added in the row
+ * @param data object data to be saved in the row
+ * @throws SQLException if there are any issues in executing insert query
+ * {@link DatabaseService#INSERT}
+ */
+ public void insert(int id, String name, Object data)
+ throws SQLException {
+ try (var connection = dataSource.getConnection();
+ var insert = connection.prepareStatement(INSERT)) {
+ insert.setInt(1, id);
+ insert.setString(2, name);
+ insert.setObject(3, data);
+ insert.execute();
+ }
+ }
+
+ /**
+ * Runs the select query {@link DatabaseService#SELECT} form the result set returns an
+ * {@link java.io.InputStream} if {@link DatabaseService#dataTypeDb} is 'binary' else will return
+ * the object as a {@link String}.
+ *
+ * @param id with which row is to be selected
+ * @param columnsName column in which the object is stored
+ * @return object found from DB
+ * @throws SQLException if there are any issues in executing insert query *
+ * {@link DatabaseService#SELECT}
+ */
+ public Object select(final long id, String columnsName) throws SQLException {
+ ResultSet resultSet = null;
+ try (var connection = dataSource.getConnection();
+ var preparedStatement =
+ connection.prepareStatement(SELECT)
+ ) {
+ Object result = null;
+ preparedStatement.setLong(1, id);
+ resultSet = preparedStatement.executeQuery();
+ while (resultSet.next()) {
+ if (dataTypeDb.equals(BINARY_DATA)) {
+ result = resultSet.getBinaryStream(columnsName);
+ } else {
+ result = resultSet.getString(columnsName);
+ }
+ }
+ return result;
+ } finally {
+ if (resultSet != null) {
+ resultSet.close();
+ }
+ }
+ }
+}
diff --git a/slob/src/main/java/com/iluwatar/slob/lob/Animal.java b/slob/src/main/java/com/iluwatar/slob/lob/Animal.java
new file mode 100644
index 000000000000..770543cc5cf3
--- /dev/null
+++ b/slob/src/main/java/com/iluwatar/slob/lob/Animal.java
@@ -0,0 +1,131 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.slob.lob;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Creates an object Animal with a list of animals and/or plants it consumes.
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class Animal implements Serializable {
+
+ private String name;
+ private Set plantsEaten = new HashSet<>();
+ private Set animalsEaten = new HashSet<>();
+
+ /**
+ * Iterates over the input nodes recursively and adds new plants to {@link Animal#plantsEaten} or
+ * animals to {@link Animal#animalsEaten} found to input sets respectively.
+ *
+ * @param childNodes contains the XML Node containing the Forest
+ * @param animalsEaten set of Animals eaten
+ * @param plantsEaten set of Plants eaten
+ */
+ protected static void iterateXmlForAnimalAndPlants(NodeList childNodes, Set animalsEaten,
+ Set plantsEaten) {
+ for (int i = 0; i < childNodes.getLength(); i++) {
+ Node child = childNodes.item(i);
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ if (child.getNodeName().equals(Animal.class.getSimpleName())) {
+ Animal animalEaten = new Animal();
+ animalEaten.createObjectFromXml(child);
+ animalsEaten.add(animalEaten);
+ } else if (child.getNodeName().equals(Plant.class.getSimpleName())) {
+ Plant plant = new Plant();
+ plant.createObjectFromXml(child);
+ plantsEaten.add(plant);
+ }
+ }
+ }
+ }
+
+ /**
+ * Provides XML Representation of the Animal.
+ *
+ * @param xmlDoc object to which the XML representation is to be written to
+ * @return XML Element contain the Animal representation
+ */
+ public Element toXmlElement(Document xmlDoc) {
+ Element root = xmlDoc.createElement(Animal.class.getSimpleName());
+ root.setAttribute("name", name);
+ for (Plant plant : plantsEaten) {
+ Element xmlElement = plant.toXmlElement(xmlDoc);
+ if (xmlElement != null) {
+ root.appendChild(xmlElement);
+ }
+ }
+ for (Animal animal : animalsEaten) {
+ Element xmlElement = animal.toXmlElement(xmlDoc);
+ if (xmlElement != null) {
+ root.appendChild(xmlElement);
+ }
+ }
+ xmlDoc.appendChild(root);
+ return (Element) xmlDoc.getFirstChild();
+ }
+
+ /**
+ * Parses the Animal Object from the input XML Node.
+ *
+ * @param node the XML Node from which the Animal Object is to be parsed
+ */
+ public void createObjectFromXml(Node node) {
+ name = node.getAttributes().getNamedItem("name").getNodeValue();
+ NodeList childNodes = node.getChildNodes();
+ iterateXmlForAnimalAndPlants(childNodes, animalsEaten, plantsEaten);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("\nAnimal Name = ").append(name);
+ if (!animalsEaten.isEmpty()) {
+ sb.append("\n\tAnimals Eaten by ").append(name).append(": ");
+ }
+ for (Animal animal : animalsEaten) {
+ sb.append("\n\t\t").append(animal);
+ }
+ sb.append("\n");
+ if (!plantsEaten.isEmpty()) {
+ sb.append("\n\tPlants Eaten by ").append(name).append(": ");
+ }
+ for (Plant plant : plantsEaten) {
+ sb.append("\n\t\t").append(plant);
+ }
+ return sb.toString();
+ }
+}
diff --git a/slob/src/main/java/com/iluwatar/slob/lob/Forest.java b/slob/src/main/java/com/iluwatar/slob/lob/Forest.java
new file mode 100644
index 000000000000..1c14d55debd8
--- /dev/null
+++ b/slob/src/main/java/com/iluwatar/slob/lob/Forest.java
@@ -0,0 +1,121 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.slob.lob;
+
+import static com.iluwatar.slob.lob.Animal.iterateXmlForAnimalAndPlants;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * Creates an object Forest which contains animals and plants as its constituents. Animals may eat
+ * plants or other animals in the forest.
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Forest implements Serializable {
+
+ private String name;
+ private Set animals = new HashSet<>();
+ private Set plants = new HashSet<>();
+
+ /**
+ * Provides the representation of Forest in XML form.
+ *
+ * @return XML Element
+ */
+ public Element toXmlElement() throws ParserConfigurationException {
+ Document xmlDoc = getXmlDoc();
+
+ Element forestXml = xmlDoc.createElement("Forest");
+ forestXml.setAttribute("name", name);
+
+ Element animalsXml = xmlDoc.createElement("Animals");
+ for (Animal animal : animals) {
+ Element animalXml = animal.toXmlElement(xmlDoc);
+ animalsXml.appendChild(animalXml);
+ }
+ forestXml.appendChild(animalsXml);
+
+ Element plantsXml = xmlDoc.createElement("Plants");
+ for (Plant plant : plants) {
+ Element plantXml = plant.toXmlElement(xmlDoc);
+ plantsXml.appendChild(plantXml);
+ }
+ forestXml.appendChild(plantsXml);
+ return forestXml;
+ }
+
+ /**
+ * Returns XMLDoc to use for XML creation.
+ *
+ * @return XML DOC Object
+ * @throws ParserConfigurationException {@inheritDoc}
+ */
+ private Document getXmlDoc() throws ParserConfigurationException {
+ return DocumentBuilderFactory.newDefaultInstance().newDocumentBuilder().newDocument();
+ }
+
+ /**
+ * Parses the Forest Object from the input XML Document.
+ *
+ * @param document the XML document from which the Forest is to be parsed
+ */
+ public void createObjectFromXml(Document document) {
+ name = document.getDocumentElement().getAttribute("name");
+ NodeList nodeList = document.getElementsByTagName("*");
+ iterateXmlForAnimalAndPlants(nodeList, animals, plants);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("\n");
+ sb.append("Forest Name = ").append(name).append("\n");
+ sb.append("Animals found in the ").append(name).append(" Forest: \n");
+ for (Animal animal : animals) {
+ sb.append("\n--------------------------\n");
+ sb.append(animal.toString());
+ sb.append("\n--------------------------\n");
+ }
+ sb.append("\n");
+ sb.append("Plants in the ").append(name).append(" Forest: \n");
+ for (Plant plant : plants) {
+ sb.append("\n--------------------------\n");
+ sb.append(plant.toString());
+ sb.append("\n--------------------------\n");
+ }
+ return sb.toString();
+ }
+}
diff --git a/slob/src/main/java/com/iluwatar/slob/lob/Plant.java b/slob/src/main/java/com/iluwatar/slob/lob/Plant.java
new file mode 100644
index 000000000000..20aff543eacb
--- /dev/null
+++ b/slob/src/main/java/com/iluwatar/slob/lob/Plant.java
@@ -0,0 +1,80 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.slob.lob;
+
+import java.io.Serializable;
+import java.util.StringJoiner;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ * Creates an object Plant which contains its name and type.
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class Plant implements Serializable {
+
+ private String name;
+ private String type;
+
+ /**
+ * Provides XML Representation of the Plant.
+ *
+ * @param xmlDoc to which the XML representation is to be written to
+ * @return XML Element contain the Animal representation
+ */
+ public Element toXmlElement(Document xmlDoc) {
+ Element root = xmlDoc.createElement(Plant.class.getSimpleName());
+ root.setAttribute("name", name);
+ root.setAttribute("type", type);
+ xmlDoc.appendChild(root);
+ return xmlDoc.getDocumentElement();
+ }
+
+ /**
+ * Parses the Plant Object from the input XML Node.
+ *
+ * @param node the XML Node from which the Animal Object is to be parsed
+ */
+ public void createObjectFromXml(Node node) {
+ NamedNodeMap attributes = node.getAttributes();
+ name = attributes.getNamedItem("name").getNodeValue();
+ type = attributes.getNamedItem("type").getNodeValue();
+ }
+
+ @Override
+ public String toString() {
+ StringJoiner stringJoiner = new StringJoiner(",");
+ stringJoiner.add("Name = " + name);
+ stringJoiner.add("Type = " + type);
+ return stringJoiner.toString();
+ }
+}
diff --git a/slob/src/main/java/com/iluwatar/slob/serializers/BlobSerializer.java b/slob/src/main/java/com/iluwatar/slob/serializers/BlobSerializer.java
new file mode 100644
index 000000000000..c3858a84a9b6
--- /dev/null
+++ b/slob/src/main/java/com/iluwatar/slob/serializers/BlobSerializer.java
@@ -0,0 +1,83 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.slob.serializers;
+
+import com.iluwatar.slob.lob.Forest;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.sql.SQLException;
+
+/**
+ * Creates a Serializer that uses Binary serialization and deserialization of objects graph to and
+ * from their Binary Representation.
+ */
+public class BlobSerializer extends LobSerializer {
+
+ public static final String TYPE_OF_DATA_FOR_DB = "BINARY";
+
+ public BlobSerializer() throws SQLException {
+ super(TYPE_OF_DATA_FOR_DB);
+ }
+
+ /**
+ * Serializes the input object graph to its Binary Representation using Object Stream.
+ *
+ * @param toSerialize Object which is to be serialized
+ * @return Serialized object
+ * @throws IOException {@inheritDoc}
+ */
+ @Override
+ public Object serialize(Forest toSerialize) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(toSerialize);
+ oos.close();
+ return new ByteArrayInputStream(baos.toByteArray());
+ }
+
+ /**
+ * Deserializes the input Byte Array Stream using Object Stream and return its Object Graph
+ * Representation.
+ *
+ * @param toDeserialize Input Object to De-serialize
+ * @return Deserialized Object
+ * @throws ClassNotFoundException {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ */
+ @Override
+ public Forest deSerialize(Object toDeserialize) throws IOException, ClassNotFoundException {
+ InputStream bis = (InputStream) toDeserialize;
+ Forest forest;
+ try (ObjectInput in = new ObjectInputStream(bis)) {
+ forest = (Forest) in.readObject();
+ }
+ return forest;
+ }
+}
diff --git a/slob/src/main/java/com/iluwatar/slob/serializers/ClobSerializer.java b/slob/src/main/java/com/iluwatar/slob/serializers/ClobSerializer.java
new file mode 100644
index 000000000000..1734447194d0
--- /dev/null
+++ b/slob/src/main/java/com/iluwatar/slob/serializers/ClobSerializer.java
@@ -0,0 +1,107 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.slob.serializers;
+
+import com.iluwatar.slob.lob.Forest;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.sql.SQLException;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+/**
+ * Creates a Serializer that uses Character based serialization and deserialization of objects graph
+ * to and from XML Representation.
+ */
+public class ClobSerializer extends LobSerializer {
+
+ public static final String TYPE_OF_DATA_FOR_DB = "TEXT";
+
+ public ClobSerializer() throws SQLException {
+ super(TYPE_OF_DATA_FOR_DB);
+ }
+
+ /**
+ * Converts the input node to its XML String Representation.
+ *
+ * @param node XML Node that is to be converted to string
+ * @return String representation of XML parsed from the Node
+ * @throws TransformerException If any issues occur in Transformation from Node to XML
+ */
+ private static String elementToXmlString(Element node) throws TransformerException {
+ StringWriter sw = new StringWriter();
+ Transformer t = TransformerFactory.newDefaultInstance().newTransformer();
+ t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+ t.setOutputProperty(OutputKeys.INDENT, "yes");
+ t.transform(new DOMSource(node), new StreamResult(sw));
+ return sw.toString();
+ }
+
+ /**
+ * Serializes the input object graph to its XML Representation using DOM Elements.
+ *
+ * @param forest Object which is to be serialized
+ * @return Serialized object
+ * @throws ParserConfigurationException If any issues occur in parsing input object
+ * @throws TransformerException If any issues occur in Transformation from Node to XML
+ */
+ @Override
+ public Object serialize(Forest forest) throws ParserConfigurationException, TransformerException {
+ Element xmlElement = forest.toXmlElement();
+ return elementToXmlString(xmlElement);
+ }
+
+ /**
+ * Deserializes the input XML string using DOM Parser and return its Object Graph Representation.
+ *
+ * @param toDeserialize Input Object to De-serialize
+ * @return Deserialized Object
+ * @throws ParserConfigurationException If any issues occur in parsing input object
+ * @throws IOException if any issues occur during reading object
+ * @throws SAXException If any issues occur in Transformation from Node to XML
+ */
+ @Override
+ public Forest deSerialize(Object toDeserialize)
+ throws ParserConfigurationException, IOException, SAXException {
+ DocumentBuilder documentBuilder = DocumentBuilderFactory.newDefaultInstance()
+ .newDocumentBuilder();
+ var stream = new ByteArrayInputStream(toDeserialize.toString().getBytes());
+ Document parsed = documentBuilder.parse(stream);
+ Forest forest = new Forest();
+ forest.createObjectFromXml(parsed);
+ return forest;
+ }
+}
diff --git a/slob/src/main/java/com/iluwatar/slob/serializers/LobSerializer.java b/slob/src/main/java/com/iluwatar/slob/serializers/LobSerializer.java
new file mode 100644
index 000000000000..54e9c8ba52ec
--- /dev/null
+++ b/slob/src/main/java/com/iluwatar/slob/serializers/LobSerializer.java
@@ -0,0 +1,115 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.slob.serializers;
+
+import com.iluwatar.slob.dbservice.DatabaseService;
+import com.iluwatar.slob.lob.Forest;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.Serializable;
+import java.sql.SQLException;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+import org.xml.sax.SAXException;
+
+/**
+ * A LobSerializer can be used to create an instance of a serializer which can serialize and
+ * deserialize an object and persist and load that object into a DB. from their Binary
+ * Representation.
+ */
+public abstract class LobSerializer implements Serializable, Closeable {
+
+ private final transient DatabaseService databaseService;
+
+ /**
+ * Constructor initializes {@link LobSerializer#databaseService}.
+ *
+ * @param dataTypeDb Input provides type of Data to be stored by the Data Base Service
+ * @throws SQLException If any issue occurs during instantiation of DB Service or during startup.
+ */
+ protected LobSerializer(String dataTypeDb) throws SQLException {
+ databaseService = new DatabaseService(dataTypeDb);
+ databaseService.startupService();
+ }
+
+ /**
+ * Provides the specification to Serialize the input object.
+ *
+ * @param toSerialize Input Object to serialize
+ * @return Serialized Object
+ * @throws ParserConfigurationException if any issue occurs during parsing of input object
+ * @throws TransformerException if any issue occurs during Transformation
+ * @throws IOException if any issues occur during reading object
+ */
+ public abstract Object serialize(Forest toSerialize)
+ throws ParserConfigurationException, TransformerException, IOException;
+
+ /**
+ * Saves the object to DB with the provided ID.
+ *
+ * @param id key to be sent to DB service
+ * @param name Object name to store in DB
+ * @param object Object to store in DB
+ * @return ID with which the object is stored in DB
+ * @throws SQLException if any issue occurs while saving to DB
+ */
+ public int persistToDb(int id, String name, Object object) throws SQLException {
+ databaseService.insert(id, name, object);
+ return id;
+ }
+
+ /**
+ * Loads the object from db using the ID and column name.
+ *
+ * @param id to query the DB
+ * @param columnName column from which object is to be extracted
+ * @return Object from DB
+ * @throws SQLException if any issue occurs while loading from DB
+ */
+ public Object loadFromDb(int id, String columnName) throws SQLException {
+ return databaseService.select(id, columnName);
+ }
+
+ /**
+ * Provides the specification to Deserialize the input object.
+ *
+ * @param toDeserialize object to deserialize
+ * @return Deserialized Object
+ * @throws ParserConfigurationException If issue occurs during parsing of input object
+ * @throws IOException if any issues occur during reading object
+ * @throws SAXException if any issues occur during reading object for XML parsing
+ */
+ public abstract Forest deSerialize(Object toDeserialize)
+ throws ParserConfigurationException, IOException, SAXException, ClassNotFoundException;
+
+ @Override
+ public void close() {
+ try {
+ databaseService.shutDownService();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/slob/src/test/java/com/iluwatar/slob/AppTest.java b/slob/src/test/java/com/iluwatar/slob/AppTest.java
new file mode 100644
index 000000000000..f8332a128020
--- /dev/null
+++ b/slob/src/test/java/com/iluwatar/slob/AppTest.java
@@ -0,0 +1,143 @@
+/*
+ * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
+ *
+ * The MIT License
+ * Copyright © 2014-2022 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.slob;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+import com.iluwatar.slob.lob.Animal;
+import com.iluwatar.slob.lob.Forest;
+import com.iluwatar.slob.lob.Plant;
+import com.iluwatar.slob.serializers.BlobSerializer;
+import com.iluwatar.slob.serializers.ClobSerializer;
+import com.iluwatar.slob.serializers.LobSerializer;
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.Set;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.xml.sax.SAXException;
+
+/**
+ * SLOB Application test
+ */
+@Slf4j
+class AppTest {
+
+ /**
+ * Creates a Forest with Animals and Plants along with their respective relationships.
+ * The method creates a forest with 2 Plants Grass and Oak of type Herb and tree
+ * respectively.
+ * It also creates 3 animals Zebra and Buffalo which eat the plant grass. Lion consumes the
+ * Zebra and the Buffalo.
+ * With the above animals and plants and their relationships a forest
+ * object is created which represents the Object Graph.
+ *
+ * @return Forest Object
+ */
+ private static Forest createForest() {
+ Plant grass = new Plant("Grass", "Herb");
+ Plant oak = new Plant("Oak", "Tree");
+
+ Animal zebra = new Animal("Zebra", Set.of(grass), Collections.emptySet());
+ Animal buffalo = new Animal("Buffalo", Set.of(grass), Collections.emptySet());
+ Animal lion = new Animal("Lion", Collections.emptySet(), Set.of(zebra, buffalo));
+
+ return new Forest("Amazon", Set.of(lion, buffalo, zebra), Set.of(grass, oak));
+ }
+
+ /**
+ * Tests the {@link App} without passing any argument in the args to test the
+ * {@link ClobSerializer}.
+ */
+ @Test
+ void shouldExecuteWithoutExceptionClob() {
+ assertDoesNotThrow(() -> App.main(new String[]{"CLOB"}));
+ }
+
+ /**
+ * Tests the {@link App} without passing any argument in the args to test the
+ * {@link BlobSerializer}.
+ */
+ @Test
+ void shouldExecuteWithoutExceptionBlob() {
+ assertDoesNotThrow(() -> App.main(new String[]{}));
+ }
+
+ /**
+ * Tests the serialization of the input object using the {@link ClobSerializer} and persists the
+ * serialized object to DB, then load the object back from DB and deserializes it using the
+ * provided {@link ClobSerializer}.After loading the object back from DB the test matches the
+ * hash of the input object with the hash of the object that was loaded from DB and deserialized.
+ */
+ @Test
+ void clobSerializerTest() {
+ Forest forest = createForest();
+ try (LobSerializer serializer = new ClobSerializer()) {
+
+ Object serialized = serializer.serialize(forest);
+ int id = serializer.persistToDb(1, forest.getName(), serialized);
+
+ Object fromDb = serializer.loadFromDb(id, Forest.class.getSimpleName());
+ Forest forestFromDb = serializer.deSerialize(fromDb);
+
+ Assertions.assertEquals(forest.hashCode(), forestFromDb.hashCode(),
+ "Hashes of objects after Serializing and Deserializing are the same");
+ } catch (SQLException | IOException | TransformerException | ParserConfigurationException |
+ SAXException |
+ ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Tests the serialization of the input object using the {@link BlobSerializer} and persists the
+ * serialized object to DB, then loads the object back from DB and deserializes it using the
+ * {@link BlobSerializer}.
After loading the object back from DB the test matches the hash of
+ * the input object with the hash of the object that was loaded from DB and deserialized.
+ */
+ @Test
+ void blobSerializerTest() {
+ Forest forest = createForest();
+ try (LobSerializer serializer = new BlobSerializer()) {
+
+ Object serialized = serializer.serialize(forest);
+ int id = serializer.persistToDb(1, forest.getName(), serialized);
+
+ Object fromDb = serializer.loadFromDb(id, Forest.class.getSimpleName());
+ Forest forestFromDb = serializer.deSerialize(fromDb);
+
+ Assertions.assertEquals(forest.hashCode(), forestFromDb.hashCode(),
+ "Hashes of objects after Serializing and Deserializing are the same");
+ } catch (SQLException | IOException | TransformerException | ParserConfigurationException |
+ SAXException |
+ ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}