feature: Implement Serialized Entity Pattern (#2150)

* Add files:
- App.java
- Country.java
- CountryDao.java
- CountrySchemaSql.java
- CountryTest.java
- README.md
- serialize-entity.urm.puml
- pom.xml (inherit from parent pom.xml)
Update files:
- pom.xml (parent pom.xml, add 1 module called serialized-entity)

* Fix duplicated error in pom.xml

* Update:
- pom.xml (module servant, changed by error, now fixed)
- pom.xml (module serialized-entity)

* Update:
- pom.xml (changed, artifactId)

* Update:
- pom.xml

Add:
AppTest.java

* Resolved changes required by the reviewer

Co-authored-by: Ilkka Seppälä <iluwatar@users.noreply.github.com>
This commit is contained in:
JurenXu
2022-11-13 11:43:03 +04:00
committed by GitHub
parent 953f9a4e0c
commit b103e44ecd
12 changed files with 816 additions and 0 deletions
+1
View File
@@ -215,6 +215,7 @@
<module>composite-view</module>
<module>metadata-mapping</module>
<module>service-to-worker</module>
<module>serialized-entity</module>
<module>identity-map</module>
</modules>
<repositories>
+221
View File
@@ -0,0 +1,221 @@
---
title: Serialized Entity Pattern
categories: Architectural
language: en
tags:
- Data access
---
## Intent
To easily persist Java objects to the database.
## Explanation
Java serialization allow us to convert the object to a set of bytes. We can store these bytes into database as
BLOB(binary long objects) and read them at any time and reconstruct them into Java objects.
**Programmatic Example**
Walking through our customers example, here's the basic `Customer` entity.
```java
@Getter
@Setter
@EqualsAndHashCode
@ToString
@AllArgsConstructor
public class Country implements Serializable {
private int code;
private String name;
private String continents;
private String language;
public static final long serialVersionUID = 7149851;
// Constructor ->
// getters and setters ->
}
```
Here is `CountrySchemaSql`, this class have method allow us to serialize `Country` object and insert it into the
database, also have a method that read serialized data from the database and deserialize it to `Country` object.
```java
@Slf4j
public class CountrySchemaSql {
public static final String CREATE_SCHEMA_SQL = "CREATE TABLE IF NOT EXISTS WORLD (ID INT PRIMARY KEY, COUNTRY BLOB)";
public static final String DELETE_SCHEMA_SQL = "DROP TABLE WORLD IF EXISTS";
private Country country;
private DataSource dataSource;
/**
* Public constructor.
*
* @param dataSource datasource
* @param country country
*/
public CountrySchemaSql(Country country, DataSource dataSource) {
this.country = new Country(
country.getCode(),
country.getName(),
country.getContinents(),
country.getLanguage()
);
this.dataSource = dataSource;
}
/**
* This method will serialize a Country object and store it to database.
* @return int type, if successfully insert a serialized object to database then return country code, else return -1.
* @throws IOException if any.
*/
public int insertCountry() throws IOException {
var sql = "INSERT INTO WORLD (ID, COUNTRY) VALUES (?, ?)";
try (var connection = dataSource.getConnection();
var preparedStatement = connection.prepareStatement(sql);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oss = new ObjectOutputStream(baos)) {
oss.writeObject(country);
oss.flush();
preparedStatement.setInt(1, country.getCode());
preparedStatement.setBlob(2, new ByteArrayInputStream(baos.toByteArray()));
preparedStatement.execute();
return country.getCode();
} catch (SQLException e) {
LOGGER.info("Exception thrown " + e.getMessage());
}
return -1;
}
/**
* This method will select a data item from database and deserialize it.
* @return int type, if successfully select and deserialized object from database then return country code,
* else return -1.
* @throws IOException if any.
* @throws ClassNotFoundException if any.
*/
public int selectCountry() throws IOException, ClassNotFoundException {
var sql = "SELECT ID, COUNTRY FROM WORLD WHERE ID = ?";
try (var connection = dataSource.getConnection();
var preparedStatement = connection.prepareStatement(sql)) {
preparedStatement.setInt(1, country.getCode());
try (ResultSet rs = preparedStatement.executeQuery()) {
if (rs.next()) {
Blob countryBlob = rs.getBlob("country");
ByteArrayInputStream baos = new ByteArrayInputStream(countryBlob.getBytes(1, (int) countryBlob.length()));
ObjectInputStream ois = new ObjectInputStream(baos);
country = (Country) ois.readObject();
LOGGER.info("Country: " + country);
}
return rs.getInt("id");
}
} catch (SQLException e) {
LOGGER.info("Exception thrown " + e.getMessage());
}
return -1;
}
}
```
This `App.java` will first delete a World table from the h2 database(if there is one) and create a new table called
`WORLD` to ensure we have a table we want.
It will then create two `Country` objects called `China` and `UnitedArabEmirates`, then create two `CountrySchemaSql`
objects and use objects `China` and `UnitedArabEmirates` as arguments.
Finally, call `SerializedChina.insertCountry()` and `serializedUnitedArabEmirates.insertCountry()` to serialize and
store them to database, and call `SerializedChina.selectCountry()` and `serializedUnitedArabEmirates.selectCountry()`
methods to read and deserialize data items to `Country` objects.
```java
@Slf4j
public class App {
private static final String DB_URL = "jdbc:h2:~/test";
private App() {
}
/**
* Program entry point.
* @param args command line args.
* @throws IOException if any
* @throws ClassNotFoundException if any
*/
public static void main(String[] args) throws IOException, ClassNotFoundException {
final var dataSource = createDataSource();
deleteSchema(dataSource);
createSchema(dataSource);
final var China = new Country(
86,
"China",
"Asia",
"Chinese"
);
final var UnitedArabEmirates = new Country(
971,
"United Arab Emirates",
"Asia",
"Arabic"
);
final var serializedChina = new CountrySchemaSql(China, dataSource);
final var serializedUnitedArabEmirates = new CountrySchemaSql(UnitedArabEmirates, dataSource);
serializedChina.insertCountry();
serializedUnitedArabEmirates.insertCountry();
serializedChina.selectCountry();
serializedUnitedArabEmirates.selectCountry();
}
private static void deleteSchema(DataSource dataSource) {
try (var connection = dataSource.getConnection();
var statement = connection.createStatement()) {
statement.execute(CountrySchemaSql.DELETE_SCHEMA_SQL);
} catch (SQLException e) {
LOGGER.info("Exception thrown " + e.getMessage());
}
}
private static void createSchema(DataSource dataSource) {
try (var connection = dataSource.getConnection();
var statement = connection.createStatement()) {
statement.execute(CountrySchemaSql.CREATE_SCHEMA_SQL);
} catch (SQLException e) {
LOGGER.info("Exception thrown " + e.getMessage());
}
}
private static DataSource createDataSource() {
var dataSource = new JdbcDataSource();
dataSource.setURL(DB_URL);
return dataSource;
}
}
```
## Class diagram
![alt_text](./etc/class_diagram.urm.png "Serialized Entity")
## Applicability
Use the Serialized Entity pattern when
* You want to easily persist Java objects to the database.
## Related patterns
[Data Access Object](https://github.com/iluwatar/java-design-patterns/tree/master/dao)
## Credits
* [J2EE Design Patterns by William Crawford, Jonathan Kaplan](https://www.oreilly.com/library/view/j2ee-design-patterns/0596004273/re21.html)
* [komminen](https://github.com/komminen/java-design-patterns) (His attempts of serialized-entity inspired me and learned a lot from his code)
Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

@@ -0,0 +1,56 @@
@startuml
package com.iluwatar.serializedentity {
class App {
- DB_URL : String {static}
- LOGGER : Logger {static}
+ App()
- createDataSource() : DataSource {static}
- createSchema(dataSource : DataSource) {static}
- deleteSchema(dataSource : DataSource) {static}
+ main(args : String[]) {static}
}
class Country {
- code : int
- name : String
- continents : String
- language : String
+ serialVersionUID : final Long {static}
~Country(int, String, String, String)
+ getCode() : int
+ getName() : String
+ getContinents() : String
+ getLanguage() : String
+ setCode(code : int)
+ setName(name : String)
+ setContinents(continents : String)
+ setLanguage(language : String)
+ equals(that: Object) : boolean
+ hashCode() : int
+ toString() : String
}
interface CountryDao {
+ insertCountry : int {abstract}
+ selectCountry : int {abstract}
}
class CountrySchemaSql {
- CREATE_SCHEMA_SQL : String {static}
- DELETE_SCHEMA_SQL : String {static}
- LOGGER : Logger {static}
- dataSource : DataSource
- country : Country
~ CountrySchemaSql(country : Country, dataSource : DataSource)
+ insertCountry()
+ selectCountry()
}
diamond h2db
}
App --> "Initialize Country objects" Country
App --> "Initialize CountrySchemaSql" CountrySchemaSql
CountrySchemaSql --> "implements" CountryDao
Country --> "Stored in database" h2db
CountrySchemaSql --> "Perform INSERT and SELECT operation after serialize and deserialize Country object" h2db
@enduml
+71
View File
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.26.0-SNAPSHOT</version>
</parent>
<artifactId>serialized-entity</artifactId>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<configuration>
<archive>
<manifest>
<mainClass>com.iluwatar.serializedentity.App</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,128 @@
/*
* 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.serializedentity;
import java.io.IOException;
import java.sql.SQLException;
import javax.sql.DataSource;
import lombok.extern.slf4j.Slf4j;
import org.h2.jdbcx.JdbcDataSource;
/**
* Serialized Entity Pattern.
*
* <p> Serialized Entity Pattern allow us to easily persist Java objects to the database. It uses Serializable interface
* and DAO pattern. Serialized Entity Pattern will first use Serializable to convert a Java object into a set of bytes,
* then it will using DAO pattern to store this set of bytes as BLOB to database.</p>
*
* <p> In this example, we first initialize two Java objects (Country) "China" and "UnitedArabEmirates", then we
* initialize "serializedChina" with "China" object and "serializedUnitedArabEmirates" with "UnitedArabEmirates",
* then we use method "serializedChina.insertCountry()" and "serializedUnitedArabEmirates.insertCountry()" to serialize
* "China" and "UnitedArabEmirates" and persist them to database.
* Last, with "serializedChina.selectCountry()" and "serializedUnitedArabEmirates.selectCountry()" we could read "China"
* and "UnitedArabEmirates" from database as sets of bytes, then deserialize them back to Java object (Country). </p>
*
*/
@Slf4j
public class App {
private static final String DB_URL = "jdbc:h2:~/test";
private App() {
}
/**
* Program entry point.
* @param args command line args.
* @throws IOException if any
* @throws ClassNotFoundException if any
*/
public static void main(String[] args) throws IOException, ClassNotFoundException {
final var dataSource = createDataSource();
deleteSchema(dataSource);
createSchema(dataSource);
// Initializing Country Object China
final var China = new Country(
86,
"China",
"Asia",
"Chinese"
);
// Initializing Country Object UnitedArabEmirates
final var UnitedArabEmirates = new Country(
971,
"United Arab Emirates",
"Asia",
"Arabic"
);
// Initializing CountrySchemaSql Object with parameter "China" and "dataSource"
final var serializedChina = new CountrySchemaSql(China, dataSource);
// Initializing CountrySchemaSql Object with parameter "UnitedArabEmirates" and "dataSource"
final var serializedUnitedArabEmirates = new CountrySchemaSql(UnitedArabEmirates, dataSource);
/*
By using CountrySchemaSql.insertCountry() method, the private (Country) type variable within Object
CountrySchemaSql will be serialized to a set of bytes and persist to database.
For more details of CountrySchemaSql.insertCountry() method please refer to CountrySchemaSql.java file
*/
serializedChina.insertCountry();
serializedUnitedArabEmirates.insertCountry();
/*
By using CountrySchemaSql.selectCountry() method, CountrySchemaSql object will read the sets of bytes from database
and deserialize it to Country object.
For more details of CountrySchemaSql.selectCountry() method please refer to CountrySchemaSql.java file
*/
serializedChina.selectCountry();
serializedUnitedArabEmirates.selectCountry();
}
private static void deleteSchema(DataSource dataSource) {
try (var connection = dataSource.getConnection();
var statement = connection.createStatement()) {
statement.execute(CountrySchemaSql.DELETE_SCHEMA_SQL);
} catch (SQLException e) {
LOGGER.info("Exception thrown " + e.getMessage());
}
}
private static void createSchema(DataSource dataSource) {
try (var connection = dataSource.getConnection();
var statement = connection.createStatement()) {
statement.execute(CountrySchemaSql.CREATE_SCHEMA_SQL);
} catch (SQLException e) {
LOGGER.info("Exception thrown " + e.getMessage());
}
}
private static DataSource createDataSource() {
var dataSource = new JdbcDataSource();
dataSource.setURL(DB_URL);
return dataSource;
}
}
@@ -0,0 +1,47 @@
/*
* 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.serializedentity;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* A Country POJO taht represents the data that will serialize and store in database.
*/
@Getter
@Setter
@EqualsAndHashCode
@ToString
@AllArgsConstructor
public class Country implements Serializable {
private int code;
private String name;
private String continents;
private String language;
public static final long serialVersionUID = 7149851;
}
@@ -0,0 +1,45 @@
/*
* 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.
*/
/**
* In an application the Data Access Object (DAO) is a part of Data access layer. It is an object
* that provides an interface to some type of persistence mechanism. By mapping application calls to
* the persistence layer, DAO provides some specific data operations without exposing details of the
* database. This isolation supports the Single responsibility principle. It separates what data
* accesses the application needs, in terms of domain-specific objects and data types (the public
* interface of the DAO), from how these needs can be satisfied with a specific DBMS, database
* schema, etc.
*
* <p>Any change in the way data is stored and retrieved will not change the client code as the
* client will be using interface and need not worry about exact source.
*
* @see InMemoryCustomerDao
* @see DbCustomerDao
*/
package com.iluwatar.serializedentity;
import java.io.IOException;
public interface CountryDao {
int insertCountry() throws IOException;
int selectCountry() throws IOException, ClassNotFoundException;
}
@@ -0,0 +1,122 @@
/*
* 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.serializedentity;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Blob;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
import lombok.extern.slf4j.Slf4j;
/**
* Country Schema SQL Class.
*/
@Slf4j
public class CountrySchemaSql implements CountryDao {
public static final String CREATE_SCHEMA_SQL = "CREATE TABLE IF NOT EXISTS WORLD (ID INT PRIMARY KEY, COUNTRY BLOB)";
public static final String DELETE_SCHEMA_SQL = "DROP TABLE WORLD IF EXISTS";
private Country country;
private DataSource dataSource;
/**
* Public constructor.
*
* @param dataSource datasource
* @param country country
*/
public CountrySchemaSql(Country country, DataSource dataSource) {
this.country = new Country(
country.getCode(),
country.getName(),
country.getContinents(),
country.getLanguage()
);
this.dataSource = dataSource;
}
/**
* This method will serialize a Country object and store it to database.
* @return int type, if successfully insert a serialized object to database then return country code, else return -1.
* @throws IOException if any.
*/
@Override
public int insertCountry() throws IOException {
var sql = "INSERT INTO WORLD (ID, COUNTRY) VALUES (?, ?)";
try (var connection = dataSource.getConnection();
var preparedStatement = connection.prepareStatement(sql);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oss = new ObjectOutputStream(baos)) {
oss.writeObject(country);
oss.flush();
preparedStatement.setInt(1, country.getCode());
preparedStatement.setBlob(2, new ByteArrayInputStream(baos.toByteArray()));
preparedStatement.execute();
return country.getCode();
} catch (SQLException e) {
LOGGER.info("Exception thrown " + e.getMessage());
}
return -1;
}
/**
* This method will select a data item from database and deserialize it.
* @return int type, if successfully select and deserialized object from database then return country code,
* else return -1.
* @throws IOException if any.
* @throws ClassNotFoundException if any.
*/
@Override
public int selectCountry() throws IOException, ClassNotFoundException {
var sql = "SELECT ID, COUNTRY FROM WORLD WHERE ID = ?";
try (var connection = dataSource.getConnection();
var preparedStatement = connection.prepareStatement(sql)) {
preparedStatement.setInt(1, country.getCode());
try (ResultSet rs = preparedStatement.executeQuery()) {
if (rs.next()) {
Blob countryBlob = rs.getBlob("country");
ByteArrayInputStream baos = new ByteArrayInputStream(countryBlob.getBytes(1, (int) countryBlob.length()));
ObjectInputStream ois = new ObjectInputStream(baos);
country = (Country) ois.readObject();
LOGGER.info("Country: " + country);
}
return rs.getInt("id");
}
} catch (SQLException e) {
LOGGER.info("Exception thrown " + e.getMessage());
}
return -1;
}
}
@@ -0,0 +1,23 @@
package com.iluwatar.serializedentity;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
/**
* Tests that Serialized Entity example runs without errors.
*/
class AppTest {
/**
* Issue: Add at least one assertion to this test case.
*
* Solution: Inserted assertion to check whether the execution of the main method in {@link App#main(String[])}
* throws an exception.
*/
@Test
void shouldExecuteSerializedEntityWithoutException() {
assertDoesNotThrow(() -> App.main(new String[]{}));
}
}
@@ -0,0 +1,101 @@
/*
* 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.serializedentity;
import org.junit.jupiter.api.Test;
import java.io.*;
import static org.junit.jupiter.api.Assertions.*;
public class CountryTest {
@Test
void testGetMethod() {
Country China = new Country(
86,
"China",
"Asia",
"Chinese"
);
assertEquals(86, China.getCode());
assertEquals("China", China.getName());
assertEquals("Asia", China.getContinents());
assertEquals("Chinese", China.getLanguage());
}
@Test
void testSetMethod() {
Country country = new Country(
86,
"China",
"Asia",
"Chinese"
);
country.setCode(971);
country.setName("UAE");
country.setContinents("West-Asia");
country.setLanguage("Arabic");
assertEquals(971, country.getCode());
assertEquals("UAE", country.getName());
assertEquals("West-Asia", country.getContinents());
assertEquals("Arabic", country.getLanguage());
}
@Test
void testSerializable(){
// Serializing Country
try {
Country country = new Country(
86,
"China",
"Asia",
"Chinese");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("output.txt"));
objectOutputStream.writeObject(country);
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
// De-serialize Country
try {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("output.txt"));
Country country = (Country) objectInputStream.readObject();
objectInputStream.close();
System.out.println(country);
Country China = new Country(
86,
"China",
"Asia",
"Chinese");
assertEquals(China, country);
} catch (Exception e) {
e.printStackTrace();
}
}
}
+1
View File
@@ -27,6 +27,7 @@
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>servant</groupId>
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>