• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

temporalio / sdk-java / #156

pending completion
#156

push

github-actions

web-flow
Provide SerializationContext for PayloadConverter and PayloadCodec (#1695)

Issue #1694

497 of 497 new or added lines in 32 files covered. (100.0%)

16928 of 20806 relevant lines covered (81.36%)

0.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

71.43
/temporal-sdk/src/main/java/io/temporal/common/converter/DataConverter.java
1
/*
2
 * Copyright (C) 2022 Temporal Technologies, Inc. All Rights Reserved.
3
 *
4
 * Copyright (C) 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5
 *
6
 * Modifications copyright (C) 2017 Uber Technologies, Inc.
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this material except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *   http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20

21
package io.temporal.common.converter;
22

23
import com.fasterxml.jackson.databind.ObjectMapper;
24
import com.google.common.base.Defaults;
25
import io.temporal.api.common.v1.Payload;
26
import io.temporal.api.common.v1.Payloads;
27
import io.temporal.api.failure.v1.Failure;
28
import io.temporal.common.Experimental;
29
import io.temporal.failure.TemporalFailure;
30
import io.temporal.payload.codec.PayloadCodec;
31
import io.temporal.payload.context.SerializationContext;
32
import java.lang.reflect.Type;
33
import java.util.Arrays;
34
import java.util.Optional;
35
import javax.annotation.Nonnull;
36

37
/**
38
 * Used by the framework to serialize/deserialize method parameters that need to be sent over the
39
 * wire.
40
 *
41
 * <h2>Most users should never implement this interface until absolutely needed.</h2>
42
 *
43
 * Instead, users should implement
44
 *
45
 * <ul>
46
 *   <li>{@link PayloadConverter} to customize Object &lt;-&gt; Payload (bytes) conversion
47
 *   <li>{@link PayloadCodec} to perform Payload (bytes) &lt;-&gt; Payload (bytes) encoding (like
48
 *       encryption or compression)
49
 * </ul>
50
 *
51
 * A custom {@link PayloadConverter} can be registered on {@link DefaultDataConverter} instance. For
52
 * that:
53
 *
54
 * <ul>
55
 *   <li>Obtain {@link DefaultDataConverter} instance from {@link
56
 *       DefaultDataConverter#newDefaultInstance()}. Register your custom {@link PayloadConverter}
57
 *       using {@link DefaultDataConverter#withPayloadConverterOverrides(PayloadConverter...)}. This
58
 *       way will preserve the standard set of {@link PayloadConverter}s supplied by Temporal
59
 *       JavaSDK other that the ones that were overridden. See {@link
60
 *       DefaultDataConverter#STANDARD_PAYLOAD_CONVERTERS})
61
 *   <li>Pass the custom {@link PayloadConverter} directly to {@link
62
 *       DefaultDataConverter#DefaultDataConverter(PayloadConverter...)} to discard the standard
63
 *       {@link PayloadConverter}s supplied by Temporal JavaSDK out of the box.
64
 * </ul>
65
 *
66
 * A {@link DataConverter} created on previous step may be bundled with {@link PayloadCodec}s using
67
 * {@link CodecDataConverter} or used directly if no custom {@link PayloadCodec}s are needed.
68
 */
69
public interface DataConverter {
70

71
  /**
72
   * @deprecated use {@link GlobalDataConverter#get()}
73
   */
74
  @Deprecated
75
  static DataConverter getDefaultInstance() {
76
    return GlobalDataConverter.get();
×
77
  }
78

79
  /**
80
   * @param value value to convert
81
   * @return a {@link Payload} which is a protobuf message containing byte-array serialized
82
   *     representation of {@code value}. Optional here is for legacy and backward compatibility
83
   *     reasons. This Optional is expected to always be filled.
84
   * @throws DataConverterException if conversion fails
85
   */
86
  <T> Optional<Payload> toPayload(T value) throws DataConverterException;
87

88
  <T> T fromPayload(Payload payload, Class<T> valueClass, Type valueType)
89
      throws DataConverterException;
90

91
  /**
92
   * Implements conversion of a list of values.
93
   *
94
   * @param values Java values to convert to String.
95
   * @return converted value. Return empty Optional if values are empty.
96
   * @throws DataConverterException if conversion of the value passed as parameter failed for any
97
   *     reason.
98
   */
99
  Optional<Payloads> toPayloads(Object... values) throws DataConverterException;
100

101
  /**
102
   * Implements conversion of an array of values of different types. Useful for deserializing
103
   * arguments of function invocations.
104
   *
105
   * @param index index of the value in the payloads
106
   * @param content serialized value to convert to Java objects.
107
   * @param valueType type of the value stored in the content
108
   * @param valueGenericType generic type of the value stored in the content
109
   * @return converted Java object
110
   * @throws DataConverterException if conversion of the data passed as parameter failed for any
111
   *     reason.
112
   */
113
  <T> T fromPayloads(
114
      int index, Optional<Payloads> content, Class<T> valueType, Type valueGenericType)
115
      throws DataConverterException;
116

117
  /**
118
   * Instantiate an appropriate Java Exception from a serialized Failure object. The default
119
   * implementation delegates the conversion process to an instance of {@link FailureConverter},
120
   * using this data converter for payload decoding.
121
   *
122
   * @param failure Failure protobuf object to deserialize into an exception
123
   * @throws NullPointerException if failure is null
124
   */
125
  @Nonnull
126
  TemporalFailure failureToException(@Nonnull Failure failure);
127

128
  /**
129
   * Serialize an existing Throwable object into a Failure object. The default implementation
130
   * delegates the conversion process to an instance of {@link FailureConverter}, using this data
131
   * converter for payload encoding.
132
   *
133
   * @param throwable a Throwable object to serialize into a Failure protobuf object
134
   * @throws NullPointerException if throwable is null
135
   */
136
  @Nonnull
137
  Failure exceptionToFailure(@Nonnull Throwable throwable);
138

139
  static Object[] arrayFromPayloads(
140
      DataConverter converter,
141
      Optional<Payloads> content,
142
      Class<?>[] parameterTypes,
143
      Type[] genericParameterTypes)
144
      throws DataConverterException {
145
    if (parameterTypes != null
1✔
146
        && (genericParameterTypes == null
147
            || parameterTypes.length != genericParameterTypes.length)) {
148
      throw new IllegalArgumentException(
×
149
          "parameterTypes don't match length of valueTypes: "
150
              + Arrays.toString(parameterTypes)
×
151
              + "<>"
152
              + Arrays.toString(genericParameterTypes));
×
153
    }
154

155
    int length = parameterTypes.length;
1✔
156
    Object[] result = new Object[length];
1✔
157
    if (!content.isPresent()) {
1✔
158
      // Return defaults for all the parameters
159
      for (int i = 0; i < parameterTypes.length; i++) {
1✔
160
        result[i] = Defaults.defaultValue((Class<?>) genericParameterTypes[i]);
×
161
      }
162
      return result;
1✔
163
    }
164
    Payloads payloads = content.get();
1✔
165
    int count = payloads.getPayloadsCount();
1✔
166
    for (int i = 0; i < parameterTypes.length; i++) {
1✔
167
      Class<?> pt = parameterTypes[i];
1✔
168
      Type gt = genericParameterTypes[i];
1✔
169
      if (i >= count) {
1✔
170
        result[i] = Defaults.defaultValue((Class<?>) gt);
1✔
171
      } else {
172
        result[i] = converter.fromPayload(payloads.getPayloads(i), pt, gt);
1✔
173
      }
174
    }
175
    return result;
1✔
176
  }
177

178
  /**
179
   * A correct implementation of this interface should have a fully functional "contextless"
180
   * implementation. Temporal SDK will call this method when a knowledge of the context exists, but
181
   * {@link DataConverter} can be used directly by user code and sometimes SDK itself without any
182
   * context.
183
   *
184
   * <p>Note: this method is expected to be cheap and fast. Temporal SDK doesn't always cache the
185
   * instances and may be calling this method very often. Users are responsible to make sure that
186
   * this method doesn't recreate expensive objects like Jackson's {@link ObjectMapper} on every
187
   * call.
188
   *
189
   * @param context provides information to the data converter about the abstraction the data
190
   *     belongs to
191
   * @return an instance of DataConverter that may use the provided {@code context} for
192
   *     serialization
193
   * @see SerializationContext
194
   */
195
  @Experimental
196
  @Nonnull
197
  default DataConverter withContext(@Nonnull SerializationContext context) {
198
    return this;
×
199
  }
200
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc