-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
2,315 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
target | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
ThisBuild / version := "0.1.0-SNAPSHOT" | ||
|
||
val scala12Version = "2.12.18" | ||
val scala13Version = "2.13.11" | ||
val scala3Version = "3.3.0" | ||
ThisBuild / scalaVersion := scala13Version | ||
ThisBuild / crossScalaVersions := Seq(scala12Version, scala13Version, scala3Version) | ||
|
||
val pekkoVersion = "1.0.1" | ||
val jacksonVersion = "2.15.2" | ||
|
||
lazy val root = (project in file(".")) | ||
.settings( | ||
name := "pekko-serialization-jackson215", | ||
libraryDependencies ++= Seq( | ||
"org.apache.pekko" %% "pekko-actor" % pekkoVersion, | ||
"org.apache.pekko" %% "pekko-actor-typed" % pekkoVersion % Optional, | ||
"org.apache.pekko" %% "pekko-stream" % pekkoVersion % Optional, | ||
"com.fasterxml.jackson.core" % "jackson-databind" % jacksonVersion, | ||
"com.fasterxml.jackson.core" % "jackson-core" % jacksonVersion, | ||
"com.fasterxml.jackson.dataformat" % "jackson-dataformat-cbor" % jacksonVersion, | ||
"com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % jacksonVersion, | ||
"com.fasterxml.jackson.module" % "jackson-module-parameter-names" % jacksonVersion, | ||
"com.fasterxml.jackson.module" %% "jackson-module-scala" % jacksonVersion, | ||
"org.lz4" % "lz4-java" % "1.8.0", | ||
"org.scala-lang.modules" %% "scala-java8-compat" % "1.0.2", | ||
"org.scalatest" %% "scalatest" % "3.2.16" % Test, | ||
"ch.qos.logback" % "logback-classic" % "1.2.12" % Test | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
sbt.version = 1.9.3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,259 @@ | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
########################################### | ||
# Pekko Serialization Jackson Config File # | ||
########################################### | ||
|
||
# This is the reference config file that contains all the default settings. | ||
# Make your edits/overrides in your application.conf. | ||
|
||
#//#jackson-modules | ||
pekko.serialization.jackson215 { | ||
|
||
# The Jackson JSON serializer will register these modules. | ||
jackson-modules += "com.github.pjfanning.pekko.serialization.jackson215.PekkoJacksonModule" | ||
# PekkoTypedJacksonModule optionally included if pekko-actor-typed is in classpath | ||
jackson-modules += "com.github.pjfanning.pekko.serialization.jackson215.PekkoTypedJacksonModule" | ||
# PekkoStreamsModule optionally included if pekko-streams is in classpath | ||
jackson-modules += "com.github.pjfanning.pekko.serialization.jackson215.PekkoStreamJacksonModule" | ||
jackson-modules += "com.fasterxml.jackson.module.paramnames.ParameterNamesModule" | ||
jackson-modules += "com.fasterxml.jackson.datatype.jdk8.Jdk8Module" | ||
jackson-modules += "com.fasterxml.jackson.datatype.jsr310.JavaTimeModule" | ||
jackson-modules += "com.fasterxml.jackson.module.scala.DefaultScalaModule" | ||
} | ||
#//#jackson-modules | ||
|
||
pekko.serialization.jackson215 { | ||
# When enabled and pekko.loglevel=DEBUG serialization time and payload size | ||
# is logged for each messages. | ||
verbose-debug-logging = off | ||
|
||
# Define data migration transformations of old formats to current | ||
# format here as a mapping between the (old) class name to be | ||
# transformed to the JacksonJsonMigration class that implements | ||
# the transformation. | ||
migrations { | ||
} | ||
|
||
} | ||
|
||
#//#stream-read-constraints | ||
pekko.serialization.jackson215 { | ||
read { | ||
# see https://www.javadoc.io/static/com.fasterxml.jackson.core/jackson-core/2.15.2/com/fasterxml/jackson/core/StreamReadConstraints.html | ||
# these defaults are the same as the defaults in `StreamReadConstraints` | ||
max-nesting-depth = 1000 | ||
max-number-length = 1000 | ||
max-string-length = 20000000 | ||
} | ||
} | ||
#//#stream-read-constraints | ||
|
||
#//#features | ||
pekko.serialization.jackson215 { | ||
# Configuration of the ObjectMapper serialization features. | ||
# See com.fasterxml.jackson.databind.SerializationFeature | ||
# Enum values corresponding to the SerializationFeature and their boolean value. | ||
serialization-features { | ||
# Date/time in ISO-8601 (rfc3339) yyyy-MM-dd'T'HH:mm:ss.SSSZ format | ||
# as defined by com.fasterxml.jackson.databind.util.StdDateFormat | ||
# For interoperability it's better to use the ISO format, i.e. WRITE_DATES_AS_TIMESTAMPS=off, | ||
# but WRITE_DATES_AS_TIMESTAMPS=on has better performance. | ||
WRITE_DATES_AS_TIMESTAMPS = off | ||
WRITE_DURATIONS_AS_TIMESTAMPS = off | ||
FAIL_ON_EMPTY_BEANS = off | ||
} | ||
|
||
# Configuration of the ObjectMapper deserialization features. | ||
# See com.fasterxml.jackson.databind.DeserializationFeature | ||
# Enum values corresponding to the DeserializationFeature and their boolean value. | ||
deserialization-features { | ||
FAIL_ON_UNKNOWN_PROPERTIES = off | ||
} | ||
|
||
# Configuration of the ObjectMapper mapper features. | ||
# See com.fasterxml.jackson.databind.MapperFeature | ||
# Enum values corresponding to the MapperFeature and their | ||
# boolean values, for example: | ||
# | ||
# mapper-features { | ||
# SORT_PROPERTIES_ALPHABETICALLY = on | ||
# } | ||
mapper-features {} | ||
|
||
# Configuration of the ObjectMapper JsonParser features. | ||
# See com.fasterxml.jackson.core.JsonParser.Feature | ||
# Enum values corresponding to the JsonParser.Feature and their | ||
# boolean value, for example: | ||
# | ||
# json-parser-features { | ||
# ALLOW_SINGLE_QUOTES = on | ||
# } | ||
json-parser-features {} | ||
|
||
# Configuration of the ObjectMapper JsonParser features. | ||
# See com.fasterxml.jackson.core.JsonGenerator.Feature | ||
# Enum values corresponding to the JsonGenerator.Feature and | ||
# their boolean value, for example: | ||
# | ||
# json-generator-features { | ||
# WRITE_NUMBERS_AS_STRINGS = on | ||
# } | ||
json-generator-features {} | ||
|
||
# Configuration of the JsonFactory StreamReadFeature. | ||
# See com.fasterxml.jackson.core.StreamReadFeature | ||
# Enum values corresponding to the StreamReadFeatures and | ||
# their boolean value, for example: | ||
# | ||
# stream-read-features { | ||
# STRICT_DUPLICATE_DETECTION = on | ||
# } | ||
stream-read-features {} | ||
|
||
# Configuration of the JsonFactory StreamWriteFeature. | ||
# See com.fasterxml.jackson.core.StreamWriteFeature | ||
# Enum values corresponding to the StreamWriteFeatures and | ||
# their boolean value, for example: | ||
# | ||
# stream-write-features { | ||
# WRITE_BIGDECIMAL_AS_PLAIN = on | ||
# } | ||
stream-write-features {} | ||
|
||
# Configuration of the JsonFactory JsonReadFeature. | ||
# See com.fasterxml.jackson.core.json.JsonReadFeature | ||
# Enum values corresponding to the JsonReadFeatures and | ||
# their boolean value, for example: | ||
# | ||
# json-read-features { | ||
# ALLOW_SINGLE_QUOTES = on | ||
# } | ||
json-read-features {} | ||
|
||
# Configuration of the JsonFactory JsonWriteFeature. | ||
# See com.fasterxml.jackson.core.json.JsonWriteFeature | ||
# Enum values corresponding to the JsonWriteFeatures and | ||
# their boolean value, for example: | ||
# | ||
# json-write-features { | ||
# WRITE_NUMBERS_AS_STRINGS = on | ||
# } | ||
json-write-features {} | ||
|
||
# Configuration of the JsonFactory Visibility. | ||
# See com.fasterxml.jackson.annotation.PropertyAccessor | ||
# and com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility | ||
# Enum values. For example, to serialize only public fields | ||
# overwrite the default values with: | ||
# | ||
# visibility { | ||
# FIELD = PUBLIC_ONLY | ||
# } | ||
# Default: all fields (including private and protected) are serialized. | ||
visibility { | ||
FIELD = ANY | ||
} | ||
|
||
# Deprecated, use `allowed-class-prefix` instead | ||
whitelist-class-prefix = [] | ||
|
||
# Additional classes that are allowed even if they are not defined in `serialization-bindings`. | ||
# This is useful when a class is not used for serialization any more and therefore removed | ||
# from `serialization-bindings`, but should still be possible to deserialize. | ||
allowed-class-prefix = ${pekko.serialization.jackson.whitelist-class-prefix} | ||
|
||
|
||
# settings for compression of the payload | ||
compression { | ||
# Compression algorithm. | ||
# - off : no compression | ||
# - gzip : using common java gzip | ||
algorithm = off | ||
|
||
# If compression is enabled with the `algorithm` setting the payload is compressed | ||
# when it's larger than this value. | ||
compress-larger-than = 0 KiB | ||
} | ||
|
||
# Whether the type should be written to the manifest. | ||
# If this is off, then either deserialization-type must be defined, or there must be exactly | ||
# one serialization binding declared for this serializer, and the type in that binding will be | ||
# used as the deserialization type. This feature will only work if that type either is a | ||
# concrete class, or if it is a supertype that uses Jackson polymorphism (ie, the | ||
# @JsonTypeInfo annotation) to store type information in the JSON itself. The intention behind | ||
# disabling this is to remove extraneous type information (ie, fully qualified class names) when | ||
# serialized objects are persisted in Pekko persistence or replicated using Pekko distributed | ||
# data. Note that Pekko remoting already has manifest compression optimizations that address this, | ||
# so for types that just get sent over remoting, this offers no optimization. | ||
type-in-manifest = on | ||
|
||
# The type to use for deserialization. | ||
# This is only used if type-in-manifest is disabled. If set, this type will be used to | ||
# deserialize all messages. This is useful if the binding configuration you want to use when | ||
# disabling type in manifest cannot be expressed as a single type. Examples of when you might | ||
# use this include when changing serializers, so you don't want this serializer used for | ||
# serialization and you haven't declared any bindings for it, but you still want to be able to | ||
# deserialize messages that were serialized with this serializer, as well as situations where | ||
# you only want some sub types of a given Jackson polymorphic type to be serialized using this | ||
# serializer. | ||
deserialization-type = "" | ||
|
||
# Specific settings for jackson-json binding can be defined in this section to | ||
# override the settings in 'pekko.serialization.jackson' | ||
jackson-json {} | ||
|
||
# Specific settings for jackson-cbor binding can be defined in this section to | ||
# override the settings in 'pekko.serialization.jackson' | ||
jackson-cbor {} | ||
|
||
# Issue #28918 for compatibility with data serialized with JacksonCborSerializer in | ||
# Akka 2.6.4 or earlier, which was plain JSON format. | ||
jackson-cbor-264 = ${pekko.serialization.jackson.jackson-cbor} | ||
|
||
} | ||
#//#features | ||
|
||
#//#compression | ||
# Compression settings for the jackson-json binding | ||
pekko.serialization.jackson215.jackson-json.compression { | ||
# Compression algorithm. | ||
# - off : no compression | ||
# - gzip : using common java gzip | ||
# - lz4 : using lz4-java | ||
algorithm = gzip | ||
|
||
# If compression is enabled with the `algorithm` setting the payload is compressed | ||
# when it's larger than this value. | ||
compress-larger-than = 32 KiB | ||
} | ||
#//#compression | ||
|
||
pekko.actor { | ||
serializers { | ||
jackson-json = "com.github.pjfanning.pekko.serialization.jackson215.JacksonJsonSerializer" | ||
jackson-cbor = "com.github.pjfanning.pekko.serialization.jackson215.JacksonCborSerializer" | ||
|
||
# Issue #28918 for compatibility with data serialized with JacksonCborSerializer in | ||
# Akka 2.6.4 or earlier, which was plain JSON format. | ||
jackson-cbor-264 = "com.github.pjfanning.pekko.serialization.jackson215.JacksonJsonSerializer" | ||
} | ||
serialization-identifiers { | ||
jackson-json = 31 | ||
jackson-cbor = 33 | ||
|
||
# Issue #28918 for compatibility with data serialized with JacksonCborSerializer in | ||
# Akka 2.6.4 or earlier, which was plain JSON format. | ||
jackson-cbor-264 = 32 | ||
} | ||
serialization-bindings { | ||
# Define bindings for classes or interfaces use Jackson serializer, e.g. | ||
# "com.example.Jsonable" = jackson-json | ||
# "com.example.MyMessage" = jackson-cbor | ||
# | ||
# For security reasons it is disallowed to bind the Jackson serializers to | ||
# open ended types that might be target to be deserialization gadgets, such as | ||
# java.lang.Object, java.io.Serializable, java.util.Comparable | ||
|
||
} | ||
} |
77 changes: 77 additions & 0 deletions
77
src/main/scala/com/github/pjfanning/pekko/serialization/jackson/ActorRefModule.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* license agreements; and to You under the Apache License, version 2.0: | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* This file is part of the Apache Pekko project, which was derived from Akka. | ||
*/ | ||
|
||
/* | ||
* Copyright (C) 2019-2022 Lightbend Inc. <https://www.lightbend.com> | ||
*/ | ||
|
||
package com.github.pjfanning.pekko.serialization.jackson | ||
|
||
// FIXME maybe move many things to `com.github.pjfanning.pekko.serialization.jackson215.internal` package? | ||
|
||
import com.fasterxml.jackson.core.JsonGenerator | ||
import com.fasterxml.jackson.core.JsonParser | ||
import com.fasterxml.jackson.core.JsonTokenId | ||
import com.fasterxml.jackson.databind.DeserializationContext | ||
import com.fasterxml.jackson.databind.SerializerProvider | ||
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer | ||
import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer | ||
import org.apache.pekko | ||
import org.apache.pekko.serialization.jackson215.ActorSystemAccess | ||
import pekko.actor.ActorRef | ||
import pekko.annotation.InternalApi | ||
|
||
/** | ||
* INTERNAL API: Adds support for serializing and deserializing [[ActorRef]]. | ||
*/ | ||
@InternalApi private[jackson] trait ActorRefModule extends JacksonModule { | ||
addSerializer(classOf[ActorRef], () => ActorRefSerializer.instance, () => ActorRefDeserializer.instance) | ||
} | ||
|
||
/** | ||
* INTERNAL API | ||
*/ | ||
@InternalApi private[jackson] object ActorRefSerializer { | ||
val instance: ActorRefSerializer = new ActorRefSerializer | ||
} | ||
|
||
/** | ||
* INTERNAL API | ||
*/ | ||
@InternalApi private[jackson] class ActorRefSerializer | ||
extends StdScalarSerializer[ActorRef](classOf[ActorRef]) | ||
with ActorSystemAccess { | ||
override def serialize(value: ActorRef, jgen: JsonGenerator, provider: SerializerProvider): Unit = { | ||
val serializedActorRef = value.path.toSerializationFormatWithAddress(currentSystem().provider.getDefaultAddress) | ||
jgen.writeString(serializedActorRef) | ||
} | ||
} | ||
|
||
/** | ||
* INTERNAL API | ||
*/ | ||
@InternalApi private[jackson] object ActorRefDeserializer { | ||
val instance: ActorRefDeserializer = new ActorRefDeserializer | ||
} | ||
|
||
/** | ||
* INTERNAL API | ||
*/ | ||
@InternalApi private[jackson] class ActorRefDeserializer | ||
extends StdScalarDeserializer[ActorRef](classOf[ActorRef]) | ||
with ActorSystemAccess { | ||
|
||
def deserialize(jp: JsonParser, ctxt: DeserializationContext): ActorRef = { | ||
if (jp.currentTokenId() == JsonTokenId.ID_STRING) { | ||
val serializedActorRef = jp.getText() | ||
currentSystem().provider.resolveActorRef(serializedActorRef) | ||
} else | ||
ctxt.handleUnexpectedToken(handledType(), jp).asInstanceOf[ActorRef] | ||
} | ||
} |
Oops, something went wrong.