CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-typesafe-akka--akka-serialization-jackson

Jackson-based JSON and CBOR serialization capabilities for the Akka toolkit, enabling efficient serialization and deserialization of Akka messages and persistent events.

Pending
Overview
Eval results
Files

object-mapper.mddocs/

ObjectMapper Management

The ObjectMapper management system provides centralized creation and configuration of Jackson ObjectMapper instances. This allows for consistent configuration across your application while supporting multiple serialization bindings with different settings.

Core ObjectMapper Provider

JacksonObjectMapperProvider

The main provider class manages a registry of ObjectMapper instances, each with a unique binding name.

/**
 * Registry of shared `ObjectMapper` instances, each with its unique `bindingName`.
 */
final class JacksonObjectMapperProvider(system: ExtendedActorSystem) extends Extension {
  
  /**
   * Returns an existing Jackson `ObjectMapper` or creates a new instance.
   * The returned `ObjectMapper` must not be modified after creation.
   * 
   * @param bindingName name of this `ObjectMapper`
   * @param jsonFactory optional `JsonFactory` such as `CBORFactory`, for plain JSON use `None`
   * @return configured ObjectMapper instance
   */
  def getOrCreate(bindingName: String, jsonFactory: Option[JsonFactory]): ObjectMapper
  
  /**
   * Creates a new instance of a Jackson `ObjectMapper` with sensible defaults.
   * 
   * @param bindingName name of this `ObjectMapper`  
   * @param jsonFactory optional `JsonFactory` such as `CBORFactory`, for plain JSON use `None`
   * @return new ObjectMapper instance
   */
  def create(bindingName: String, jsonFactory: Option[JsonFactory]): ObjectMapper
}

Accessing the Provider

import akka.actor.ActorSystem
import akka.serialization.jackson.JacksonObjectMapperProvider

val system = ActorSystem("MySystem")
val provider = JacksonObjectMapperProvider(system)

Getting ObjectMapper Instances

For JSON serialization:

val jsonMapper = provider.getOrCreate("my-json-binding", None)

For CBOR serialization:

import com.fasterxml.jackson.dataformat.cbor.CBORFactory

val cborMapper = provider.getOrCreate("my-cbor-binding", Some(new CBORFactory()))

Creating fresh instances:

// Create a new mapper instead of using cached version
val freshMapper = provider.create("my-binding", None)

Custom ObjectMapper Factory

JacksonObjectMapperFactory

For advanced customization, you can provide a custom factory that controls ObjectMapper creation and configuration.

/**
 * Factory for creating and customizing ObjectMapper instances.
 * Create a subclass and override methods to amend the defaults.
 */
class JacksonObjectMapperFactory {
  
  /**
   * Override to create custom ObjectMapper instance.
   * 
   * @param bindingName name of this `ObjectMapper`
   * @param jsonFactory optional `JsonFactory` for the mapper
   * @return new ObjectMapper instance
   */
  def newObjectMapper(bindingName: String, jsonFactory: JsonFactory): ObjectMapper
  
  /**
   * Override configured Jackson modules.
   * 
   * @param bindingName binding name for this mapper
   * @param configuredModules modules configured in akka.serialization.jackson.jackson-modules
   * @return modules to be applied to the ObjectMapper
   */
  def overrideConfiguredModules(bindingName: String, configuredModules: immutable.Seq[Module]): immutable.Seq[Module]
  
  /**
   * Override serialization features.
   * 
   * @param bindingName binding name for this mapper
   * @param configuredFeatures features configured in akka.serialization.jackson.serialization-features
   * @return features to be applied to the ObjectMapper
   */
  def overrideConfiguredSerializationFeatures(bindingName: String, configuredFeatures: immutable.Seq[(SerializationFeature, Boolean)]): immutable.Seq[(SerializationFeature, Boolean)]
  
  /**
   * Override deserialization features.
   * 
   * @param bindingName binding name for this mapper
   * @param configuredFeatures features configured in akka.serialization.jackson.deserialization-features  
   * @return features to be applied to the ObjectMapper
   */
  def overrideConfiguredDeserializationFeatures(bindingName: String, configuredFeatures: immutable.Seq[(DeserializationFeature, Boolean)]): immutable.Seq[(DeserializationFeature, Boolean)]
  
  /**
   * Override mapper features.
   * 
   * @param bindingName binding name for this mapper
   * @param configuredFeatures features configured in akka.serialization.jackson.mapper-features
   * @return features to be applied to the ObjectMapper
   */
  def overrideConfiguredMapperFeatures(bindingName: String, configuredFeatures: immutable.Seq[(MapperFeature, Boolean)]): immutable.Seq[(MapperFeature, Boolean)]
  
  /**
   * Override JSON parser features.
   * 
   * @param bindingName binding name for this mapper
   * @param configuredFeatures features configured in akka.serialization.jackson.json-parser-features
   * @return features to be applied to the ObjectMapper
   */
  def overrideConfiguredJsonParserFeatures(bindingName: String, configuredFeatures: immutable.Seq[(JsonParser.Feature, Boolean)]): immutable.Seq[(JsonParser.Feature, Boolean)]
  
  /**
   * Override JSON generator features.
   * 
   * @param bindingName binding name for this mapper
   * @param configuredFeatures features configured in akka.serialization.jackson.json-generator-features
   * @return features to be applied to the ObjectMapper
   */
  def overrideConfiguredJsonGeneratorFeatures(bindingName: String, configuredFeatures: immutable.Seq[(JsonGenerator.Feature, Boolean)]): immutable.Seq[(JsonGenerator.Feature, Boolean)]
  
  /**
   * Override stream read features.
   * 
   * @param bindingName binding name for this mapper
   * @param configuredFeatures features configured in akka.serialization.jackson.stream-read-features
   * @return features to be applied to the JsonFactory
   */
  def overrideConfiguredStreamReadFeatures(bindingName: String, configuredFeatures: immutable.Seq[(StreamReadFeature, Boolean)]): immutable.Seq[(StreamReadFeature, Boolean)]
  
  /**
   * Override stream write features.
   * 
   * @param bindingName binding name for this mapper
   * @param configuredFeatures features configured in akka.serialization.jackson.stream-write-features
   * @return features to be applied to the JsonFactory
   */
  def overrideConfiguredStreamWriteFeatures(bindingName: String, configuredFeatures: immutable.Seq[(StreamWriteFeature, Boolean)]): immutable.Seq[(StreamWriteFeature, Boolean)]
  
  /**
   * Override JSON read features.
   * 
   * @param bindingName binding name for this mapper
   * @param configuredFeatures features configured in akka.serialization.jackson.json-read-features
   * @return features to be applied to the JsonFactory
   */
  def overrideConfiguredJsonReadFeatures(bindingName: String, configuredFeatures: immutable.Seq[(JsonReadFeature, Boolean)]): immutable.Seq[(JsonReadFeature, Boolean)]
  
  /**
   * Override JSON write features.
   * 
   * @param bindingName binding name for this mapper
   * @param configuredFeatures features configured in akka.serialization.jackson.json-write-features
   * @return features to be applied to the JsonFactory
   */
  def overrideConfiguredJsonWriteFeatures(bindingName: String, configuredFeatures: immutable.Seq[(JsonWriteFeature, Boolean)]): immutable.Seq[(JsonWriteFeature, Boolean)]
  
  /**
   * Override visibility settings.
   * 
   * @param bindingName binding name for this mapper
   * @param configuredFeatures visibility settings configured in akka.serialization.jackson.visibility
   * @return visibility settings to be applied to the ObjectMapper
   */
  def overrideConfiguredVisibility(bindingName: String, configuredFeatures: immutable.Seq[(PropertyAccessor, JsonAutoDetect.Visibility)]): immutable.Seq[(PropertyAccessor, JsonAutoDetect.Visibility)]
}

Custom Factory Example

class MyCustomFactory extends JacksonObjectMapperFactory {
  override def newObjectMapper(bindingName: String, jsonFactory: JsonFactory): ObjectMapper = {
    val mapper = JsonMapper.builder(jsonFactory).build()
    // Add custom configuration
    mapper.configure(SerializationFeature.INDENT_OUTPUT, true)
    mapper
  }
  
  override def overrideConfiguredModules(bindingName: String, configuredModules: immutable.Seq[Module]): immutable.Seq[Module] = {
    // Add a custom module
    configuredModules :+ new MyCustomJacksonModule()
  }
}

Factory Setup

JacksonObjectMapperProviderSetup

To use a custom factory, provide it during ActorSystem creation:

/**
 * Setup for defining a custom JacksonObjectMapperFactory.
 */
final class JacksonObjectMapperProviderSetup(val factory: JacksonObjectMapperFactory) extends Setup

object JacksonObjectMapperProviderSetup {
  /**
   * Create setup with custom factory (Scala API).
   * 
   * @param factory custom JacksonObjectMapperFactory
   * @return setup instance for ActorSystem
   */
  def apply(factory: JacksonObjectMapperFactory): JacksonObjectMapperProviderSetup
  
  /**
   * Create setup with custom factory (Java API).
   * 
   * @param factory custom JacksonObjectMapperFactory
   * @return setup instance for ActorSystem
   */
  def create(factory: JacksonObjectMapperFactory): JacksonObjectMapperProviderSetup
}

Using Custom Factory

import akka.actor.ActorSystem
import akka.actor.setup.ActorSystemSetup
import akka.serialization.jackson.{JacksonObjectMapperProviderSetup, JacksonObjectMapperFactory}

val customFactory = new MyCustomFactory()
val setup = JacksonObjectMapperProviderSetup(customFactory)
val actorSystemSetup = ActorSystemSetup(setup)
val system = ActorSystem("MySystem", actorSystemSetup)

Configuration Integration

The ObjectMapper provider integrates with Akka configuration system, reading settings from akka.serialization.jackson section:

Binding-Specific Configuration

akka.serialization.jackson {
  # Global settings
  jackson-modules += "com.example.MyModule"
  
  # Binding-specific settings  
  my-json-binding {
    serialization-features {
      INDENT_OUTPUT = on
    }
  }
  
  my-cbor-binding {
    compression {
      algorithm = lz4
      compress-larger-than = 1 KiB
    }
  }
}

Accessing Binding Configuration

import akka.serialization.jackson.JacksonObjectMapperProvider

val config = JacksonObjectMapperProvider.configForBinding("my-binding", system.settings.config)
val isCompressionEnabled = config.getString("compression.algorithm") != "off"

Best Practices

  1. Use getOrCreate() for shared mappers - Reuses configured instances for better performance
  2. Use create() for specialized mappers - When you need mapper-specific customizations
  3. Don't modify returned ObjectMappers - They may be shared across threads
  4. Use binding names consistently - Match names used in serialization-bindings configuration
  5. Configure features through setup or configuration - Avoid runtime ObjectMapper modifications
  6. Cache factory instances - Custom factories can be expensive to create

Install with Tessl CLI

npx tessl i tessl/maven-com-typesafe-akka--akka-serialization-jackson

docs

akka-types.md

configuration.md

index.md

migration.md

object-mapper.md

tile.json