Skip to content

Commit 429092f

Browse files
committed
Merge branch '2.19'
2 parents 14006dc + 10fc1ba commit 429092f

File tree

11 files changed

+129
-30
lines changed

11 files changed

+129
-30
lines changed

.github/workflows/dep_build_v2.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ jobs:
1919
env:
2020
JAVA_OPTS: "-XX:+TieredCompilation -XX:TieredStopAtLevel=1"
2121
steps:
22-
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
22+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
2323
- name: Set up JDK
24-
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
24+
uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0
2525
with:
2626
distribution: 'temurin'
2727
java-version: ${{ matrix.java_version }}

.github/workflows/dep_build_v3.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ jobs:
1919
env:
2020
JAVA_OPTS: "-XX:+TieredCompilation -XX:TieredStopAtLevel=1"
2121
steps:
22-
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
22+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
2323
with:
2424
ref: master
2525
- name: Set up JDK
26-
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
26+
uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0
2727
with:
2828
distribution: 'temurin'
2929
java-version: ${{ matrix.java_version }}

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ jobs:
6060
run: ./mvnw -B -q -ff -ntp test
6161
- name: Publish code coverage
6262
if: ${{ matrix.release_build && github.event_name != 'pull_request' }}
63-
uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # v5.0.7
63+
uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e # v5.1.1
6464
with:
6565
token: ${{ secrets.CODECOV_TOKEN }}
6666
file: ./target/site/jacoco/jacoco.xml

avro/README.md

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -114,32 +114,34 @@ and that's about it, for now.
114114

115115
## Avro Logical Types
116116

117-
Following is an extract from [Logical Types](http://avro.apache.org/docs/current/specification/_print/#logical-types) paragraph in
118-
Avro schema specification:
117+
The following is an excerpt from the [Logical Types](https://avro.apache.org/docs/1.11.1/specification/#logical-types) section of
118+
the Avro schema specification:
119+
119120
> A logical type is an Avro primitive or complex type with extra attributes to represent a derived type. The attribute
120-
> `logicalType` is always be present for a logical type, and is a string with the name of one of the logical types
121-
> defined by Avro specification.
121+
> `logicalType` must always be present for a logical type, and is a string with the name of one of the logical types
122+
> listed later in this section. Other attributes may be defined for particular logical types.
123+
124+
Logical types are supported for a limited set of `java.time` classes and for 'java.util.UUID'. See the table below for more details.
122125

123-
Generation of logical types for limited set of `java.time` classes is supported at the moment. See a table bellow.
126+
### Mapping to Logical Types
124127

125-
### Mapping to Logical Type
128+
Mapping to Avro type and logical type involves these steps:
126129

127-
Mapping to Avro type and logical type works in few steps:
128-
1. Serializer for particular Java type (or class) determines a Jackson type where the Java type will be serialized into.
129-
2. `AvroSchemaGenerator` determines corresponding Avro type for that Jackson type.
130-
2. If logical type generation is enabled, then `logicalType` is determined for the above combination of Java type and
131-
Avro type.
130+
1. The serializer for a Java type identifies the Jackson type it will serialize into.
131+
2. The `AvroSchemaGenerator` maps that Jackson type to the corresponding Avro type.
132+
3. `logicalType` value is combination of Java type and Jackson type.
132133

133134
#### Java type to Avro Logical Type mapping
134135

135-
| Java type | Serialization type | Generated Avro schema with Avro type and logical type
136-
| ----------------------------- | ------------------ | -----------------------------------------------------
137-
| `java.time.OffsetDateTime` | NumberType.LONG | `{"type": "long", "logicalType": "timestamp-millis"}`
138-
| `java.time.ZonedDateTime` | NumberType.LONG | `{"type": "long", "logicalType": "timestamp-millis"}`
139-
| `java.time.Instant` | NumberType.LONG | `{"type": "long", "logicalType": "timestamp-millis"}`
140-
| `java.time.LocalDate` | NumberType.INT | `{"type": "int", "logicalType": "date"}`
141-
| `java.time.LocalTime` | NumberType.INT | `{"type": "int", "logicalType": "time-millis"}`
142-
| `java.time.LocalDateTime` | NumberType.LONG | `{"type": "long", "logicalType": "local-timestamp-millis"}`
136+
| Java type | Jackson type | Generated Avro schema with logical type |
137+
|----------------------------|-----------------|---------------------------------------------------------------------------------------------------|
138+
| `java.time.OffsetDateTime` | NumberType.LONG | `{"type": "long", "logicalType": "timestamp-millis"}` |
139+
| `java.time.ZonedDateTime` | NumberType.LONG | `{"type": "long", "logicalType": "timestamp-millis"}` |
140+
| `java.time.Instant` | NumberType.LONG | `{"type": "long", "logicalType": "timestamp-millis"}` |
141+
| `java.time.LocalDate` | NumberType.INT | `{"type": "int", "logicalType": "date"}` |
142+
| `java.time.LocalTime` | NumberType.INT | `{"type": "int", "logicalType": "time-millis"}` |
143+
| `java.time.LocalDateTime` | NumberType.LONG | `{"type": "long", "logicalType": "local-timestamp-millis"}` |
144+
| `java.util.UUID` (2.19+) | | `{"type": "fixed", "name": "UUID", "namespace": "java.util", "size": 16, "logicalType" : "uuid"}` |
143145

144146
_Provided Avro logical type generation is enabled._
145147

avro/src/main/java/tools/jackson/dataformat/avro/schema/AvroSchemaHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ public static Schema createEnumSchema(MapperConfig<?> config, JavaType enumType,
272272
* @since 2.11
273273
*/
274274
public static Schema createUUIDSchema() {
275-
return Schema.createFixed("UUID", "", "java.util", 16);
275+
return Schema.createFixed("UUID", null, "java.util", 16);
276276
}
277277

278278
/**

avro/src/main/java/tools/jackson/dataformat/avro/schema/StringVisitor.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,6 @@ public Schema builtAvroSchema() {
4040
// should we construct JavaType for `Character.class` in case of primitive or... ?
4141
return AvroSchemaHelper.numericAvroSchema(NumberType.INT, _type);
4242
}
43-
// [dataformats-binary#179]: need special help with UUIDs, to coerce into Binary
44-
// (could actually be
45-
if (_type.hasRawClass(java.util.UUID.class)) {
46-
return AvroSchemaHelper.createUUIDSchema();
47-
}
4843
AnnotatedClass annotations = _provider.introspectClassAnnotations(_type);
4944
Schema schema = Schema.create(Schema.Type.STRING);
5045
// Stringable classes need to include the type
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package tools.jackson.dataformat.avro.schema;
2+
3+
import java.util.Set;
4+
5+
import tools.jackson.databind.jsonFormatVisitors.JsonStringFormatVisitor;
6+
import tools.jackson.databind.jsonFormatVisitors.JsonValueFormat;
7+
8+
import org.apache.avro.LogicalTypes;
9+
import org.apache.avro.Schema;
10+
11+
/**
12+
* Visitor for {@link java.util.UUID} type. When it is created with logicalTypesEnabled enabled,
13+
* Avro schema is created with logical type uuid.
14+
*
15+
* @since 2.19
16+
*/
17+
public class UUIDVisitor extends JsonStringFormatVisitor.Base
18+
implements SchemaBuilder {
19+
protected boolean _logicalTypesEnabled = false;
20+
21+
22+
public UUIDVisitor(boolean logicalTypesEnabled) {
23+
_logicalTypesEnabled = logicalTypesEnabled;
24+
}
25+
26+
@Override
27+
public void format(JsonValueFormat format) {
28+
// Ideally, we'd recognize UUIDs, Dates etc if need be, here...
29+
}
30+
31+
@Override
32+
public void enumTypes(Set<String> enums) {
33+
// Do nothing
34+
}
35+
36+
@Override
37+
public Schema builtAvroSchema() {
38+
// [dataformats-binary#179]: need special help with UUIDs, to coerce into Binary
39+
// (could actually be
40+
Schema schema = AvroSchemaHelper.createUUIDSchema();
41+
return this._logicalTypesEnabled ? LogicalTypes.uuid().addToSchema(schema) : schema;
42+
}
43+
}

avro/src/main/java/tools/jackson/dataformat/avro/schema/VisitorFormatWrapperImpl.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,12 @@ public JsonStringFormatVisitor expectStringFormat(JavaType type)
198198
return v;
199199
}
200200

201+
if (type.hasRawClass(java.util.UUID.class)) {
202+
UUIDVisitor v = new UUIDVisitor(this._logicalTypesEnabled);
203+
_builder = v;
204+
return v;
205+
}
206+
201207
StringVisitor v = new StringVisitor(_context, type);
202208
_builder = v;
203209
return v;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package tools.jackson.dataformat.avro.schema;
2+
3+
import org.junit.Test;
4+
5+
import org.apache.avro.LogicalType;
6+
import org.apache.avro.Schema;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
10+
public class UUIDVisitor_builtAvroSchemaTest {
11+
12+
@Test
13+
public void testLogicalTypesDisabled() {
14+
// GIVEN
15+
boolean logicalTypesEnabled = false;
16+
UUIDVisitor uuidVisitor = new UUIDVisitor(logicalTypesEnabled);
17+
18+
// WHEN
19+
Schema actualSchema = uuidVisitor.builtAvroSchema();
20+
21+
// THEN
22+
assertThat(actualSchema.getType()).isEqualTo(Schema.Type.FIXED);
23+
assertThat(actualSchema.getFixedSize()).isEqualTo(16);
24+
assertThat(actualSchema.getName()).isEqualTo("UUID");
25+
assertThat(actualSchema.getNamespace()).isEqualTo("java.util");
26+
assertThat(actualSchema.getProp(LogicalType.LOGICAL_TYPE_PROP)).isNull();
27+
}
28+
29+
@Test
30+
public void testLogicalTypesEnabled() {
31+
// GIVEN
32+
boolean logicalTypesEnabled = true;
33+
UUIDVisitor uuidVisitor = new UUIDVisitor(logicalTypesEnabled);
34+
35+
// WHEN
36+
Schema actualSchema = uuidVisitor.builtAvroSchema();
37+
38+
// THEN
39+
assertThat(actualSchema.getType()).isEqualTo(Schema.Type.FIXED);
40+
assertThat(actualSchema.getFixedSize()).isEqualTo(16);
41+
assertThat(actualSchema.getName()).isEqualTo("UUID");
42+
assertThat(actualSchema.getNamespace()).isEqualTo("java.util");
43+
assertThat(actualSchema.getProp(LogicalType.LOGICAL_TYPE_PROP)).isEqualTo("uuid");
44+
}
45+
46+
}

release-notes/CREDITS-2.x

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ Michal Foksa (MichalFoksa@github)
225225
* Contributed #494: Avro Schema generation: allow mapping Java Enum properties to
226226
Avro String values
227227
(2.18.0)
228+
* Contributed #536: (avro) Add Logical Type support for `java.util.UUID`
229+
(2.19.0)
228230

229231
Hunter Herman (hherman1@github)
230232

0 commit comments

Comments
 (0)