Skip to content

Commit afee810

Browse files
Merge pull request #18479 from AndreiBranza/BAEL-8051-serialize-enum-value-in-avro
[BAEL-8051-serialize-enum-value-in-avro] - article code
2 parents 40b7e1f + d210927 commit afee810

File tree

1 file changed

+179
-0
lines changed

1 file changed

+179
-0
lines changed
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
package com.baeldung.apache.avro;
2+
3+
import org.apache.avro.Schema;
4+
import org.apache.avro.SchemaBuilder;
5+
import org.apache.avro.file.DataFileReader;
6+
import org.apache.avro.file.DataFileWriter;
7+
import org.apache.avro.generic.GenericData;
8+
import org.apache.avro.generic.GenericDatumReader;
9+
import org.apache.avro.generic.GenericDatumWriter;
10+
import org.apache.avro.generic.GenericRecord;
11+
import org.apache.avro.io.DatumReader;
12+
import org.apache.avro.io.DatumWriter;
13+
import org.junit.jupiter.api.BeforeEach;
14+
import org.junit.jupiter.api.Test;
15+
import org.junit.jupiter.api.io.TempDir;
16+
17+
import java.io.File;
18+
import java.io.IOException;
19+
import java.nio.file.Path;
20+
21+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
22+
import static org.junit.jupiter.api.Assertions.assertEquals;
23+
24+
public class SerializeEnumValueInAvroUnitTest {
25+
26+
@TempDir
27+
Path tempDir;
28+
29+
private Schema colorEnum;
30+
private Schema recordSchema;
31+
private Schema unionSchema;
32+
private Schema recordWithUnionSchema;
33+
34+
@BeforeEach
35+
void setUp() {
36+
// Create enum schema
37+
colorEnum = SchemaBuilder.enumeration("Color")
38+
.namespace("com.baeldung.apache.avro")
39+
.symbols("UNKNOWN", "GREEN", "RED", "BLUE");
40+
41+
// Create record schema with enum field
42+
recordSchema = SchemaBuilder.record("ColorRecord")
43+
.namespace("com.baeldung.apache.avro")
44+
.fields()
45+
.name("color")
46+
.type(colorEnum)
47+
.noDefault()
48+
.endRecord();
49+
50+
// Create union schema with enum and null
51+
unionSchema = SchemaBuilder.unionOf()
52+
.type(colorEnum)
53+
.and()
54+
.nullType()
55+
.endUnion();
56+
57+
// Create record schema with union field
58+
recordWithUnionSchema = SchemaBuilder.record("ColorRecordWithUnion")
59+
.namespace("com.baeldung.apache.avro")
60+
.fields()
61+
.name("color")
62+
.type(unionSchema)
63+
.noDefault()
64+
.endRecord();
65+
}
66+
67+
@Test
68+
void whenSerializingEnum_thenSuccess() throws IOException {
69+
File file = tempDir.resolve("color.avro").toFile();
70+
71+
// Create record with enum value
72+
GenericRecord record = new GenericData.Record(recordSchema);
73+
GenericData.EnumSymbol colorSymbol = new GenericData.EnumSymbol(colorEnum, "RED");
74+
record.put("color", colorSymbol);
75+
76+
// Write to file
77+
DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>(recordSchema);
78+
try (DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<>(datumWriter)) {
79+
dataFileWriter.create(recordSchema, file);
80+
dataFileWriter.append(record);
81+
}
82+
83+
// Read from file
84+
DatumReader<GenericRecord> datumReader = new GenericDatumReader<>(recordSchema);
85+
try (DataFileReader<GenericRecord> dataFileReader = new DataFileReader<>(file, datumReader)) {
86+
GenericRecord result = dataFileReader.next();
87+
assertEquals("RED", result.get("color").toString());
88+
}
89+
}
90+
91+
@Test
92+
void whenSerializingEnumInUnion_thenSuccess() throws IOException {
93+
File file = tempDir.resolve("colorUnion.avro").toFile();
94+
95+
// Create record with enum in union
96+
GenericRecord record = new GenericData.Record(recordWithUnionSchema);
97+
GenericData.EnumSymbol colorSymbol = new GenericData.EnumSymbol(colorEnum, "GREEN");
98+
record.put("color", colorSymbol);
99+
100+
// Write to file
101+
DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>(recordWithUnionSchema);
102+
try (DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<>(datumWriter)) {
103+
dataFileWriter.create(recordWithUnionSchema, file);
104+
dataFileWriter.append(record);
105+
}
106+
107+
// Read from file
108+
DatumReader<GenericRecord> datumReader = new GenericDatumReader<>(recordWithUnionSchema);
109+
try (DataFileReader<GenericRecord> dataFileReader = new DataFileReader<>(file, datumReader)) {
110+
GenericRecord result = dataFileReader.next();
111+
assertEquals("GREEN", result.get("color").toString());
112+
}
113+
}
114+
115+
@Test
116+
void whenSerializingNullInUnion_thenSuccess() throws IOException {
117+
File file = tempDir.resolve("colorNull.avro").toFile();
118+
119+
// Create record with null in union
120+
GenericRecord record = new GenericData.Record(recordWithUnionSchema);
121+
record.put("color", null);
122+
123+
// Write to file
124+
DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>(recordWithUnionSchema);
125+
assertDoesNotThrow(() -> {
126+
try (DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<>(datumWriter)) {
127+
dataFileWriter.create(recordWithUnionSchema, file);
128+
dataFileWriter.append(record);
129+
}
130+
});
131+
}
132+
133+
@Test
134+
void whenSchemaEvolution_thenDefaultValueUsed() throws IOException {
135+
// Create schema with new enum value and default at schema level
136+
String evolvedSchemaJson = "{\"type\":\"record\"," +
137+
"\"name\":\"ColorRecord\"," +
138+
"\"namespace\":\"com.baeldung.apache.avro\"," +
139+
"\"fields\":[{\"name\":\"color\"," +
140+
"\"type\":{\"type\":\"enum\"," +
141+
"\"name\":\"Color\"," +
142+
"\"symbols\":[\"UNKNOWN\",\"GREEN\",\"RED\",\"BLUE\",\"YELLOW\"]," +
143+
"\"default\":\"UNKNOWN\"}}]}";
144+
145+
Schema evolvedRecordSchema = new Schema.Parser().parse(evolvedSchemaJson);
146+
Schema evolvedEnum = evolvedRecordSchema.getField("color").schema();
147+
148+
File file = tempDir.resolve("colorEvolved.avro").toFile();
149+
150+
// Create record with new enum value
151+
GenericRecord record = new GenericData.Record(evolvedRecordSchema);
152+
GenericData.EnumSymbol colorSymbol = new GenericData.EnumSymbol(evolvedEnum, "YELLOW");
153+
record.put("color", colorSymbol);
154+
155+
// Write with evolved schema
156+
DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>(evolvedRecordSchema);
157+
try (DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<>(datumWriter)) {
158+
dataFileWriter.create(evolvedRecordSchema, file);
159+
dataFileWriter.append(record);
160+
}
161+
162+
// Create old schema without YELLOW but WITH default
163+
String originalSchemaJson = "{\"type\":\"record\"," +
164+
"\"name\":\"ColorRecord\"," +
165+
"\"namespace\":\"com.baeldung.apache.avro\"," +
166+
"\"fields\":[{\"name\":\"color\",\"type\":{\"type\":\"enum\",\"name\":\"Color\"," +
167+
"\"symbols\":[\"UNKNOWN\",\"GREEN\",\"RED\",\"BLUE\"]," +
168+
"\"default\":\"UNKNOWN\"}}]}";
169+
170+
Schema originalRecordSchema = new Schema.Parser().parse(originalSchemaJson);
171+
172+
// Read with original schema
173+
DatumReader<GenericRecord> datumReader = new GenericDatumReader<>(evolvedRecordSchema, originalRecordSchema);
174+
try (DataFileReader<GenericRecord> dataFileReader = new DataFileReader<>(file, datumReader)) {
175+
GenericRecord result = dataFileReader.next();
176+
assertEquals("UNKNOWN", result.get("color").toString());
177+
}
178+
}
179+
}

0 commit comments

Comments
 (0)