Interface PayloadCodec


public interface PayloadCodec
Payload codec.

This allows to transform journal payloads after they're serialized, before they're written to the wire, and before they're deserialized after they're read from the wire. A typical use case is service side journal encryption.

Payloads that are passed through the codec:

  • Handlers input and success output
  • ctx.run success results
  • Call/send parameters and call success results
  • Awakeables, durable promises and signals success results
  • State values

Failures (e.g. terminal error messages), state keys, headers and other metadata are not passed through the codec.

The encoding/decoding doesn't need to be deterministic, see isEncodingDeterministic().

The codec can be configured in the endpoint with Endpoint.Builder#withPayloadCodec(PayloadCodec), and in the ingress client with Client.connect(String, SerdeFactory, PayloadCodec, RequestOptions).

Implementations of this class MUST be thread safe and asynchronous, as they might block the I/O thread.

NOTE: Using this class in a service requires the native state machine, available on JDK 23+.

  • Field Details

  • Method Details

    • encode

      CompletableFuture<Slice> encode(Slice payload)
      Encodes the given payload. This is applied after serialization.
      Parameters:
      payload - the payload to encode. Empty slices must be handled as well.
      Returns:
      a future completed with the encoded payload
    • decode

      CompletableFuture<Slice> decode(Slice payload)
      Decodes the given payload. This is applied before deserialization.
      Parameters:
      payload - the payload to decode.
      Returns:
      a future completed with the decoded payload
    • isEncodingDeterministic

      default boolean isEncodingDeterministic()
      Whether encode(Slice) is deterministic, that is, whether encoding the same payload twice always produces the same bytes.

      When replaying an invocation, the SDK re-executes the handler code and, by default, checks that the payloads it produces (e.g. state values, call parameters, handler output) are equal to the payloads recorded in the journal by the previous execution. If they differ, the invocation fails with a journal mismatch error, as this usually signals non-deterministic handler code.

      This check compares encoded payloads. If the encoding is not deterministic, e.g. when encrypting with a random IV/nonce as AES-GCM requires, the same payload encodes to different bytes on every execution, and the check would fail on every replay. Return false in that case, and the SDK will skip the comparison of payloads when replaying. Every other journal check (e.g. the sequence of operations, the call targets, the state keys) stays enabled.

      Returns:
      true if encoding the same payload always produces the same bytes.