From fa04b17e1ddbf9081b1d3fcdd6015367de8058dd Mon Sep 17 00:00:00 2001 From: luca Date: Mon, 9 Sep 2024 12:55:43 +0200 Subject: [PATCH 1/2] feat: data class to and from byte buffer --- core-kotlin-modules/core-kotlin-11/README.md | 1 + core-kotlin-modules/core-kotlin-11/pom.xml | 60 +++++++++++++++++++ .../baeldung/dataclasstobytebuffer/User.kt | 54 +++++++++++++++++ .../UserInputOutputStream.kt | 27 +++++++++ .../UserSerialization.kt | 24 ++++++++ .../DataClassToByteBufferUnitTest.kt | 56 +++++++++++++++++ core-kotlin-modules/pom.xml | 1 + 7 files changed, 223 insertions(+) create mode 100644 core-kotlin-modules/core-kotlin-11/README.md create mode 100644 core-kotlin-modules/core-kotlin-11/pom.xml create mode 100644 core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/User.kt create mode 100644 core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/UserInputOutputStream.kt create mode 100644 core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/UserSerialization.kt create mode 100644 core-kotlin-modules/core-kotlin-11/src/test/kotlin/com/baeldung/dataclasstobytebuffer/DataClassToByteBufferUnitTest.kt diff --git a/core-kotlin-modules/core-kotlin-11/README.md b/core-kotlin-modules/core-kotlin-11/README.md new file mode 100644 index 000000000..6d3fb9a84 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-11/README.md @@ -0,0 +1 @@ +### Relevant Articles \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-11/pom.xml b/core-kotlin-modules/core-kotlin-11/pom.xml new file mode 100644 index 000000000..d9a3f7435 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-11/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + core-kotlin-11 + core-kotlin-11 + jar + + + com.baeldung + core-kotlin-modules + 1.0.0-SNAPSHOT + + + + + org.jetbrains.kotlin + kotlin-maven-serialization + ${kotlin.version} + + + org.jetbrains.kotlinx + kotlinx-serialization-json + 1.4.1 + + + com.esotericsoftware.kryo + kryo + 2.24.0 + + + + + src/main/kotlin + src/test/kotlin + + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + + + compile + compile + + compile + + + + + + kotlinx-serialization + + + + + + diff --git a/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/User.kt b/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/User.kt new file mode 100644 index 000000000..c61ec1abf --- /dev/null +++ b/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/User.kt @@ -0,0 +1,54 @@ +package com.baeldung.dataclasstobytebuffer + +import com.esotericsoftware.kryo.Kryo +import com.esotericsoftware.kryo.io.Input +import com.esotericsoftware.kryo.io.Output +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.nio.ByteBuffer + +data class User(val id: Int, val name: String, val age: Int) + +fun User.manualToByteBuffer(): ByteBuffer { + val nameBytes = this.name.toByteArray(Charsets.UTF_8) + val buffer = ByteBuffer.allocate(Int.SIZE_BYTES + nameBytes.size + Int.SIZE_BYTES) + + buffer.putInt(this.id) + buffer.put(nameBytes) + buffer.putInt(this.age) + + buffer.flip() // Prepare the buffer for reading + + return buffer +} + +fun ByteBuffer.manualToUser(): User { + val id = this.int + val nameBytes = ByteArray(this.remaining() - Int.SIZE_BYTES) + this.get(nameBytes) + val name = String(nameBytes, Charsets.UTF_8) + val age = this.int + + return User(id, name, age) +} + +// Using Kryo + +fun User.toByteBufferWithKryo(kryo: Kryo): ByteBuffer { + val byteArrayOutputStream = ByteArrayOutputStream() + val output = Output(byteArrayOutputStream) + kryo.writeObject(output, this) + output.close() + + val byteArray = byteArrayOutputStream.toByteArray() + return ByteBuffer.wrap(byteArray) +} + +fun ByteBuffer.toUserWithKryo(kryo: Kryo): User { + val byteArray = ByteArray(this.remaining()) + this.get(byteArray) + + val byteArrayInputStream = ByteArrayInputStream(byteArray) + val input = Input(byteArrayInputStream) + return kryo.readObject(input, User::class.java).also { input.close() } +} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/UserInputOutputStream.kt b/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/UserInputOutputStream.kt new file mode 100644 index 000000000..b9e20845c --- /dev/null +++ b/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/UserInputOutputStream.kt @@ -0,0 +1,27 @@ +package com.baeldung.dataclasstobytebuffer + +import java.io.* +import java.nio.ByteBuffer + +class UserInputOutputStream(val id: Int, val name: String, val age: Int) : Serializable + +fun UserInputOutputStream.outputStreamByteBuffer(): ByteBuffer { + val byteArrayOutputStream = ByteArrayOutputStream() + val objectOutputStream = ObjectOutputStream(byteArrayOutputStream) + + objectOutputStream.writeObject(this) + objectOutputStream.flush() + + val byteArray = byteArrayOutputStream.toByteArray() + return ByteBuffer.wrap(byteArray) +} + +fun ByteBuffer.inputStreamToUser(): UserInputOutputStream { + val byteArray = ByteArray(this.remaining()) + this.get(byteArray) + + val byteArrayInputStream = ByteArrayInputStream(byteArray) + val objectInputStream = ObjectInputStream(byteArrayInputStream) + + return objectInputStream.readObject() as UserInputOutputStream +} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/UserSerialization.kt b/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/UserSerialization.kt new file mode 100644 index 000000000..e354d0520 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/UserSerialization.kt @@ -0,0 +1,24 @@ +package com.baeldung.dataclasstobytebuffer + +import kotlinx.serialization.Serializable +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import java.nio.ByteBuffer +import java.nio.charset.StandardCharsets + +@Serializable +data class UserSerialization(val id: Int, val name: String, val age: Int) + +fun UserSerialization.userToJson(): ByteBuffer { + val jsonString = Json.encodeToString(this) + val byteArray = jsonString.toByteArray() + return ByteBuffer.wrap(byteArray) +} + +fun ByteBuffer.jsonToUser(): UserSerialization { + val byteArray = ByteArray(this.remaining()) + this.get(byteArray) + val jsonString = String(byteArray, StandardCharsets.UTF_8) + return Json.decodeFromString(jsonString) +} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-11/src/test/kotlin/com/baeldung/dataclasstobytebuffer/DataClassToByteBufferUnitTest.kt b/core-kotlin-modules/core-kotlin-11/src/test/kotlin/com/baeldung/dataclasstobytebuffer/DataClassToByteBufferUnitTest.kt new file mode 100644 index 000000000..9f0011a51 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-11/src/test/kotlin/com/baeldung/dataclasstobytebuffer/DataClassToByteBufferUnitTest.kt @@ -0,0 +1,56 @@ +package com.baeldung.dataclasstobytebuffer + +import com.esotericsoftware.kryo.Kryo +import org.junit.Test +import org.junit.jupiter.api.Assertions.assertEquals + +class DataClassToByteBufferUnitTest { + + private val kryo = Kryo().apply { + register(User::class.java) + } + + @Test + fun `Manual serialize and deserialize with fixed size`() { + val user = User(id = 1, name = "Alice", age = 30) + + val serializedUser = user.manualToByteBuffer() + + val deserializedUser = serializedUser.manualToUser() + + assertEquals(user, deserializedUser) + } + + @Test + fun `Serialize and deserialize using byte array output and input stream`() { + val user = UserInputOutputStream(id = 1, name = "Alice", age = 30) + + val serializedUser = user.outputStreamByteBuffer() + + val deserializedUser = serializedUser.inputStreamToUser() + + assertEquals(user, deserializedUser) + } + + @Test + fun `Serialize and deserialize using kotlin serialization library`() { + val user = UserSerialization(id = 1, name = "Alice", age = 30) + + val serializedUser = user.userToJson() + + val deserializedUser = serializedUser.jsonToUser() + + assertEquals(user, deserializedUser) + } + + @Test + fun `Serialize and deserialize using Kryo library`() { + val user = User(id = 1, name = "Alice", age = 30) + + val serializedUser = user.toByteBufferWithKryo(kryo) + + val deserializedUser = serializedUser.toUserWithKryo(kryo) + + assertEquals(user, deserializedUser) + } +} \ No newline at end of file diff --git a/core-kotlin-modules/pom.xml b/core-kotlin-modules/pom.xml index da10acd07..3cc6201ca 100644 --- a/core-kotlin-modules/pom.xml +++ b/core-kotlin-modules/pom.xml @@ -25,6 +25,7 @@ core-kotlin-8 core-kotlin-9 core-kotlin-10 + core-kotlin-11 core-kotlin-advanced core-kotlin-advanced-2 core-kotlin-advanced-3 From 90e5c967ccd006f7636b83a25d22f5ba0c053e0a Mon Sep 17 00:00:00 2001 From: luca Date: Sun, 15 Sep 2024 21:44:27 +0200 Subject: [PATCH 2/2] fix: properties in xml, user class --- core-kotlin-modules/core-kotlin-11/pom.xml | 9 +++++++-- .../kotlin/com/baeldung/dataclasstobytebuffer/User.kt | 2 +- .../dataclasstobytebuffer/UserInputOutputStream.kt | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/core-kotlin-modules/core-kotlin-11/pom.xml b/core-kotlin-modules/core-kotlin-11/pom.xml index d9a3f7435..b9a682ed4 100644 --- a/core-kotlin-modules/core-kotlin-11/pom.xml +++ b/core-kotlin-modules/core-kotlin-11/pom.xml @@ -23,12 +23,12 @@ org.jetbrains.kotlinx kotlinx-serialization-json - 1.4.1 + ${kotlinx.serialization.version} com.esotericsoftware.kryo kryo - 2.24.0 + ${kryo.version} @@ -57,4 +57,9 @@ + + + 1.4.1 + 2.24.0 + diff --git a/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/User.kt b/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/User.kt index c61ec1abf..e54498c99 100644 --- a/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/User.kt +++ b/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/User.kt @@ -7,7 +7,7 @@ import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.nio.ByteBuffer -data class User(val id: Int, val name: String, val age: Int) +data class User(val id: Int = 0, val name: String = "", val age: Int = 0) fun User.manualToByteBuffer(): ByteBuffer { val nameBytes = this.name.toByteArray(Charsets.UTF_8) diff --git a/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/UserInputOutputStream.kt b/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/UserInputOutputStream.kt index b9e20845c..b0d4a071c 100644 --- a/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/UserInputOutputStream.kt +++ b/core-kotlin-modules/core-kotlin-11/src/main/kotlin/com/baeldung/dataclasstobytebuffer/UserInputOutputStream.kt @@ -3,7 +3,7 @@ package com.baeldung.dataclasstobytebuffer import java.io.* import java.nio.ByteBuffer -class UserInputOutputStream(val id: Int, val name: String, val age: Int) : Serializable +data class UserInputOutputStream(val id: Int, val name: String, val age: Int) : Serializable fun UserInputOutputStream.outputStreamByteBuffer(): ByteBuffer { val byteArrayOutputStream = ByteArrayOutputStream()