0
# Akka Type Serialization
1
2
Akka Serialization Jackson provides built-in serialization support for Akka-specific types through specialized Jackson modules. These modules handle the complexities of serializing distributed system references and Akka-specific data types.
3
4
## Core Jackson Modules
5
6
### AkkaJacksonModule
7
8
The comprehensive module that includes support for all core Akka types.
9
10
```scala { .api }
11
/**
12
* Complete module with support for all custom serializers.
13
* Includes ActorRef, Address, and FiniteDuration serialization.
14
*/
15
class AkkaJacksonModule extends JacksonModule
16
with ActorRefModule with AddressModule with FiniteDurationModule {
17
override def getModuleName = "AkkaJacksonModule"
18
}
19
20
object AkkaJacksonModule extends AkkaJacksonModule
21
```
22
23
### AkkaTypedJacksonModule
24
25
Module for Akka Typed ActorRef serialization support.
26
27
```scala { .api }
28
/**
29
* Module for Akka Typed ActorRef serialization.
30
* Only available if akka-actor-typed is on the classpath.
31
*/
32
class AkkaTypedJacksonModule extends JacksonModule with TypedActorRefModule {
33
override def getModuleName = "AkkaTypedJacksonModule"
34
}
35
36
object AkkaTypedJacksonModule extends AkkaTypedJacksonModule
37
```
38
39
### AkkaStreamJacksonModule
40
41
Module for Akka Streams reference serialization.
42
43
```scala { .api }
44
/**
45
* Module for Akka Streams serialization (SourceRef, SinkRef).
46
* Only available if akka-streams is on the classpath.
47
*/
48
class AkkaStreamJacksonModule extends JacksonModule with StreamRefModule {
49
override def getModuleName = "AkkaStreamJacksonModule"
50
}
51
52
object AkkaStreamJacksonModule extends AkkaStreamJacksonModule
53
```
54
55
## Supported Akka Types
56
57
### ActorRef Serialization
58
59
Classic ActorRef references are serialized as strings using their serialization format.
60
61
```scala
62
import akka.actor.{ActorRef, ActorSystem}
63
64
// ActorRef is automatically serialized to string format
65
val myActor: ActorRef = system.actorOf(Props[MyActor], "myActor")
66
67
// JSON representation:
68
// "akka://MySystem@hostname:2552/user/myActor"
69
```
70
71
**Serialization behavior:**
72
- Uses `ActorRef.path.toSerializationFormatWithAddress()`
73
- Includes the full actor system address for remote resolution
74
- Handles both local and remote ActorRef instances
75
76
### Typed ActorRef Serialization
77
78
Akka Typed ActorRef instances are serialized using the ActorRefResolver.
79
80
```scala
81
import akka.actor.typed.{ActorRef, ActorSystem}
82
import akka.actor.typed.scaladsl.Behaviors
83
84
// Typed ActorRef is automatically serialized
85
val typedActor: ActorRef[String] =
86
system.systemActorOf(Behaviors.receiveMessage[String](msg => Behaviors.same), "typedActor")
87
88
// JSON representation:
89
// "akka://MySystem@hostname:2552/system/typedActor#1234567890"
90
```
91
92
**Serialization behavior:**
93
- Uses `ActorRefResolver.toSerializationFormat()`
94
- Maintains type safety during deserialization
95
- Supports both system and user-created typed actors
96
97
### Address Serialization
98
99
Akka Address instances are serialized as URI strings.
100
101
```scala
102
import akka.actor.{Address, AddressFromURIString}
103
104
val address = Address("akka", "MySystem", "hostname", 2552)
105
106
// JSON representation:
107
// "akka://MySystem@hostname:2552"
108
```
109
110
**Serialization behavior:**
111
- Uses `Address.toString()` for serialization
112
- Uses `AddressFromURIString()` for deserialization
113
- Handles all address components (protocol, system, host, port)
114
115
### FiniteDuration Serialization
116
117
Scala FiniteDuration instances are serialized using Java 8 time format.
118
119
```scala
120
import scala.concurrent.duration._
121
122
val duration = 30.seconds
123
124
// JSON representation (ISO-8601 duration format):
125
// "PT30S"
126
```
127
128
**Serialization behavior:**
129
- Delegates to Jackson's `DurationSerializer` from `jackson-modules-java8`
130
- Converts between Scala `FiniteDuration` and Java `Duration`
131
- Uses ISO-8601 duration format for JSON representation
132
133
### StreamRef Serialization
134
135
Akka Streams SourceRef and SinkRef are serialized using StreamRefResolver.
136
137
```scala
138
import akka.stream.{SourceRef, SinkRef}
139
import akka.stream.scaladsl.{Source, Sink}
140
141
// SourceRef serialization
142
val sourceRef: SourceRef[String] = Source(1 to 100).map(_.toString).runWith(StreamRefs.sourceRef())
143
144
// SinkRef serialization
145
val sinkRef: SinkRef[String] = StreamRefs.sinkRef[String]().run()
146
147
// JSON representations:
148
// SourceRef: "sourceRef://MySystem@hostname:2552/temp/$a#1234567890"
149
// SinkRef: "sinkRef://MySystem@hostname:2552/temp/$b#0987654321"
150
```
151
152
**Serialization behavior:**
153
- Uses `StreamRefResolver.toSerializationFormat()` for serialization
154
- Uses `StreamRefResolver.resolveSourceRef()` / `resolveSinkRef()` for deserialization
155
- Maintains stream materialization context
156
157
## Module Configuration
158
159
### Automatic Module Registration
160
161
The Jackson modules are automatically registered based on classpath detection:
162
163
```hocon
164
akka.serialization.jackson {
165
jackson-modules += "akka.serialization.jackson.AkkaJacksonModule"
166
# Conditionally loaded if akka-actor-typed is available
167
jackson-modules += "akka.serialization.jackson.AkkaTypedJacksonModule"
168
# Conditionally loaded if akka-streams is available
169
jackson-modules += "akka.serialization.jackson.AkkaStreamJacksonModule"
170
}
171
```
172
173
### Manual Module Registration
174
175
For custom ObjectMapper instances:
176
177
```scala
178
import akka.serialization.jackson._
179
import com.fasterxml.jackson.databind.ObjectMapper
180
181
val mapper = new ObjectMapper()
182
183
// Register individual modules
184
mapper.registerModule(AkkaJacksonModule)
185
mapper.registerModule(AkkaTypedJacksonModule)
186
mapper.registerModule(AkkaStreamJacksonModule)
187
188
// Or register through custom factory
189
class MyObjectMapperFactory extends JacksonObjectMapperFactory {
190
override def overrideConfiguredModules(bindingName: String, configuredModules: Seq[Module]): Seq[Module] = {
191
configuredModules ++ Seq(
192
AkkaJacksonModule,
193
AkkaTypedJacksonModule,
194
AkkaStreamJacksonModule
195
)
196
}
197
}
198
```
199
200
## Usage Examples
201
202
### Serializing Messages with ActorRef
203
204
```scala
205
import akka.actor.ActorRef
206
207
case class MessageWithActorRef(text: String, replyTo: ActorRef)
208
209
// Usage
210
val message = MessageWithActorRef("Hello", sender())
211
212
// JSON output:
213
// {
214
// "text": "Hello",
215
// "replyTo": "akka://MySystem@hostname:2552/user/sender#1234567890"
216
// }
217
```
218
219
### Serializing Events with Duration
220
221
```scala
222
import scala.concurrent.duration._
223
224
case class TimedEvent(name: String, duration: FiniteDuration, timestamp: Long)
225
226
// Usage
227
val event = TimedEvent("processing", 5.minutes, System.currentTimeMillis())
228
229
// JSON output:
230
// {
231
// "name": "processing",
232
// "duration": "PT5M",
233
// "timestamp": 1640995200000
234
// }
235
```
236
237
### Serializing Stream References
238
239
```scala
240
import akka.stream.{SourceRef, SinkRef}
241
242
case class StreamingJob(id: String, dataSource: SourceRef[String], resultSink: SinkRef[String])
243
244
// Usage - when serialized, refs become strings that can be resolved remotely
245
val job = StreamingJob("job-123", sourceRef, sinkRef)
246
247
// JSON output:
248
// {
249
// "id": "job-123",
250
// "dataSource": "sourceRef://MySystem@hostname:2552/temp/$a#1234567890",
251
// "resultSink": "sinkRef://MySystem@hostname:2552/temp/$b#0987654321"
252
// }
253
```
254
255
## Typed ActorRef Patterns
256
257
### Message with Typed Reply
258
259
```scala
260
import akka.actor.typed.ActorRef
261
262
case class Request(data: String, replyTo: ActorRef[Response])
263
case class Response(result: String)
264
265
// The typed ActorRef maintains type information in the serialized form
266
val request = Request("process this", typedResponseActor)
267
```
268
269
### System Actor References
270
271
```scala
272
import akka.actor.typed.{ActorSystem, SpawnProtocol}
273
274
val system: ActorSystem[SpawnProtocol.Command] = ActorSystem(Behaviors.setup[SpawnProtocol.Command] { ctx =>
275
SpawnProtocol()
276
}, "MySystem")
277
278
// System actors are serialized with system path
279
val systemActor = system.systemActorOf(myBehavior, "systemService")
280
```
281
282
## Deserialization Context
283
284
### ActorSystem Access
285
286
All Akka type deserializers require access to the current ActorSystem:
287
288
```scala
289
import akka.serialization.Serialization
290
291
// The current ActorSystem is available during deserialization
292
// through Serialization.currentTransportInformation
293
val currentSystem = Serialization.currentTransportInformation.value.system
294
```
295
296
**Note:** This context is automatically managed by Akka's serialization system and doesn't require manual setup.
297
298
## Error Handling
299
300
### Invalid ActorRef References
301
302
```scala
303
// If an ActorRef path cannot be resolved during deserialization:
304
// - For classic ActorRef: returns deadLetters ActorRef
305
// - For typed ActorRef: may throw exception depending on resolver configuration
306
```
307
308
### Missing Dependencies
309
310
```scala
311
// If akka-actor-typed is not on the classpath:
312
// - AkkaTypedJacksonModule will not be loaded
313
// - Typed ActorRef serialization will not be available
314
315
// If akka-streams is not on the classpath:
316
// - AkkaStreamJacksonModule will not be loaded
317
// - StreamRef serialization will not be available
318
```
319
320
## Performance Considerations
321
322
1. **ActorRef Resolution**: Deserializing ActorRef instances requires actor system lookup
323
2. **Remote References**: Cross-system ActorRef serialization includes full addresses
324
3. **StreamRef Lifecycle**: Serialized StreamRef instances maintain stream materialization
325
4. **Duration Conversion**: FiniteDuration serialization involves Scala/Java conversion
326
327
## Best Practices
328
329
1. **Use appropriate modules** - Only include modules for Akka features you use
330
2. **Handle resolution failures** - ActorRef deserialization may fail if actors don't exist
331
3. **Consider ref lifecycles** - Serialized ActorRef/StreamRef may outlive the original actors/streams
332
4. **Test across systems** - Verify serialization works across different ActorSystem instances
333
5. **Monitor performance** - Type serialization adds overhead compared to primitive types