Skip to content

Commit

Permalink
Serialization to java 21 (#594)
Browse files Browse the repository at this point in the history
  • Loading branch information
timyates authored Oct 18, 2023
1 parent 45bc144 commit c8bb3b1
Show file tree
Hide file tree
Showing 31 changed files with 432 additions and 20 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/graalvm-latest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ jobs:
runs-on: ubuntu-latest
strategy:
max-parallel: 6
matrix: ${{ fromJson(needs.build_matrix.outputs.matrix) }}
matrix:
java: ['17', '21']
native_test_task: ${{ fromJson(needs.build_matrix.outputs.matrix).native_test_task }}
env:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
GRADLE_ENTERPRISE_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USERNAME }}
Expand All @@ -46,7 +48,7 @@ jobs:
id: pre-build
with:
distribution: 'graalvm'
java: '17'
java: ${{ matrix.java }}
- name: Build Steps
uses: micronaut-projects/github-actions/graalvm/build@master
id: build
Expand All @@ -60,4 +62,4 @@ jobs:
uses: micronaut-projects/github-actions/graalvm/post-build@master
id: post-build
with:
java: '17'
java: ${{ matrix.java }}
4 changes: 2 additions & 2 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
java: ['17']
java: ['17', '21']
env:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
GRADLE_ENTERPRISE_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USERNAME }}
Expand Down Expand Up @@ -64,7 +64,7 @@ jobs:
./gradlew check --no-daemon --continue
- name: "🔎 Run static analysis"
if: env.SONAR_TOKEN != ''
if: env.SONAR_TOKEN != '' && matrix.java == '17'
run: |
./gradlew sonar
Expand Down
10 changes: 10 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import org.sonarqube.gradle.SonarExtension

plugins {
id("io.micronaut.build.internal.docs")
id("io.micronaut.build.internal.quality-reporting")
Expand All @@ -6,3 +8,11 @@ plugins {
repositories {
mavenCentral()
}

if (System.getenv("SONAR_TOKEN") != null) {
configure<SonarExtension> {
properties {
property("sonar.exclusions", "**/example/**")
}
}
}
1 change: 1 addition & 0 deletions buildSrc/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ dependencies {
implementation (libs.gradle.micronaut)
implementation (libs.kotlin.gradle.plugin)
implementation (libs.kotlin.gradle.allopen)
implementation (libs.kotlin.gradle.ksp)
}
32 changes: 32 additions & 0 deletions doc-examples/example-kotlin-ksp/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
id("org.jetbrains.kotlin.jvm")
id("com.google.devtools.ksp")
id("io.micronaut.build.internal.serde-examples")
}

micronaut {
runtime("netty")
testRuntime("junit5")
}

dependencies {
ksp(projects.micronautSerdeProcessor)

implementation(projects.micronautSerdeJackson)
implementation(mn.micronaut.http.client)

runtimeOnly(mnLogging.logback.classic)

testImplementation(mnTest.micronaut.test.junit5)
}

java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "17"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package example

import io.micronaut.runtime.Micronaut.*
import io.micronaut.serde.annotation.SerdeImport

fun main(args: Array<String>) {
build()
.args(*args)
.packages("com.example")
.start()
}

@SerdeImport(
value = Product::class,
mixin = ProductMixin::class) // <1>
class Serdes {}
10 changes: 10 additions & 0 deletions doc-examples/example-kotlin-ksp/src/main/kotlin/example/Book.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package example

import com.fasterxml.jackson.annotation.JsonProperty
import io.micronaut.serde.annotation.Serdeable

@Serdeable // <1>
data class Book (
val title: String, // <2>
@JsonProperty("qty") val quantity: Int
)
24 changes: 24 additions & 0 deletions doc-examples/example-kotlin-ksp/src/main/kotlin/example/Feature.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package example

import io.micronaut.core.convert.ConversionContext
import io.micronaut.core.convert.TypeConverter
import jakarta.inject.Singleton
import java.util.*

class Feature(private val name: String) {
fun name(): String {
return name
}

override fun toString(): String { // <1>
return name
}
}

@Singleton
class FeatureConverter : TypeConverter<String, Feature> {
// <2>
override fun convert(value: String, targetType: Class<Feature>, context: ConversionContext): Optional<Feature> {
return Optional.of(Feature(value))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package example

import io.micronaut.serde.annotation.Serdeable

@Serdeable
data class Location(
val features: Map<Feature, Point>
)
11 changes: 11 additions & 0 deletions doc-examples/example-kotlin-ksp/src/main/kotlin/example/Person.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package example

import com.fasterxml.jackson.annotation.JsonFilter
import io.micronaut.serde.annotation.Serdeable

@Serdeable
@JsonFilter("person-filter") // <1>
data class Person(
val name: String,
val preferredName: String?
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package example

import io.micronaut.serde.PropertyFilter
import io.micronaut.serde.Serializer
import jakarta.inject.Named
import jakarta.inject.Singleton

@Singleton
@Named("person-filter") // <1>
class PersonFilter : PropertyFilter {

override fun shouldInclude(
encoderContext: Serializer.EncoderContext,
propertySerializer: Serializer<Any>,
bean: Any,
propertyName: String,
propertyValue: Any?
): Boolean {
if (bean is Person) { // <2>
if (propertyName == "name") {
return bean.preferredName == null
} else if (propertyName == "preferredName") {
return bean.preferredName != null
}
}
return true
}
}
18 changes: 18 additions & 0 deletions doc-examples/example-kotlin-ksp/src/main/kotlin/example/Place.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package example

import io.micronaut.serde.annotation.Serdeable
import io.micronaut.serde.annotation.Serdeable.Deserializable
import io.micronaut.serde.annotation.Serdeable.Serializable

@Serdeable
data class Place(
@Deserializable(using = ReversePointSerde::class) // <1>
@Serializable(using = ReversePointSerde::class) // <2>
val point: Point,

@Serdeable.Serializable(using = example.ReversePointSerde::class)
val pointCustomSer: Point,

@Deserializable(using = ReversePointSerde::class)
val pointCustomDes: Point
)
13 changes: 13 additions & 0 deletions doc-examples/example-kotlin-ksp/src/main/kotlin/example/Point.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package example

class Point private constructor(private val x: Int, private val y: Int) {
fun coords(): IntArray {
return intArrayOf(x, y)
}

companion object {
fun valueOf(x: Int, y: Int): Point {
return Point(x, y)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package example

import io.micronaut.core.type.Argument
import io.micronaut.serde.*
import jakarta.inject.Singleton

@Singleton // <1>
class PointSerde : Serde<Point> { // <2>
override fun deserialize(
decoder: Decoder,
context: Deserializer.DecoderContext,
type: Argument<in Point>
): Point {
decoder.decodeArray().use { // <3>
val x = it.decodeInt()
val y = it.decodeInt()
return Point.valueOf(x, y) // <4>
}
}

override fun serialize(
encoder: Encoder,
context: Serializer.EncoderContext,
type: Argument<out Point>,
value: Point
) {
val coords = value.coords()
encoder.encodeArray(type).use { // <6>
it.encodeInt(coords[0])
it.encodeInt(coords[1])
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package example

class Product(val name: String, val quantity: Int)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package example

import com.fasterxml.jackson.annotation.JsonProperty

interface ProductMixin {
@get:JsonProperty("p_name")
val name: String

@get:JsonProperty("p_quantity")
val quantity: Int
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package example

import io.micronaut.context.annotation.Secondary
import io.micronaut.core.type.Argument
import io.micronaut.serde.*
import jakarta.inject.Singleton
import java.util.*

@Singleton
@Secondary // <1>
class ReversePointSerde : Serde<Point> {
override fun deserialize(
decoder: Decoder,
context: Deserializer.DecoderContext,
type: Argument<in Point>
): Point {
val array = decoder.decodeArray()
val y = array.decodeInt() // <2>
val x = array.decodeInt()
array.finishStructure()
return Point.valueOf(x, y)
}

override fun serialize(
encoder: Encoder,
context: Serializer.EncoderContext,
type: Argument<out Point>,
value: Point
) {
Objects.requireNonNull(value, "Point cannot be null")
val coords = value.coords()
val array = encoder.encodeArray(type)
array.encodeInt(coords[1]) // <3>
array.encodeInt(coords[0])
array.finishStructure()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package example

import io.micronaut.serde.ObjectMapper
import io.micronaut.test.extensions.junit5.annotation.MicronautTest
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test

@MicronautTest
class BookTest {
@Test
fun testWriteReadBook(objectMapper: ObjectMapper) {
val result = objectMapper.writeValueAsString(Book("The Stand", 50))
val book = objectMapper.readValue(result, Book::class.java)
Assertions.assertNotNull(book)
Assertions.assertEquals(
"The Stand", book.title
)
Assertions.assertEquals(50, book.quantity)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package example

import io.micronaut.serde.ObjectMapper
import io.micronaut.test.extensions.junit5.annotation.MicronautTest
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test

@MicronautTest
class LocationTest {
@Test
fun testLocation(objectMapper: ObjectMapper) {
val features = mapOf(Feature("Tree") to Point.valueOf(100, 50))
val result = objectMapper.writeValueAsString(
Location(features)
)
val location = objectMapper.readValue(result, Location::class.java)
Assertions.assertNotNull(location)
Assertions.assertEquals(1, location.features.size)
val name: String = location.features.keys.first().name()
Assertions.assertEquals("Tree", name)
}
}
Loading

0 comments on commit c8bb3b1

Please sign in to comment.