Skip to content

Commit 84f363c

Browse files
authored
[Avro] @AvroNamespace annotation to override Avro type namespace (#324)
New annotation @AvroNamespace to override Avro schema field namespace. Current namespace value is Java package name. This annotation allows to override its name.
1 parent f2a3fd2 commit 84f363c

File tree

3 files changed

+108
-5
lines changed

3 files changed

+108
-5
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.fasterxml.jackson.dataformat.avro.annotations;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
/**
9+
* Annotation allows to override default Avro type namespace value.
10+
* Default value is Java package name.
11+
*/
12+
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
13+
@Retention(RetentionPolicy.RUNTIME)
14+
public @interface AvroNamespace {
15+
String value();
16+
}

avro/src/main/java/com/fasterxml/jackson/dataformat/avro/schema/AvroSchemaHelper.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.fasterxml.jackson.dataformat.avro.schema;
22

3-
import com.fasterxml.jackson.databind.util.LRUMap;
43
import java.io.File;
54
import java.math.BigDecimal;
65
import java.math.BigInteger;
@@ -23,6 +22,8 @@
2322
import com.fasterxml.jackson.databind.json.JsonMapper;
2423
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatTypes;
2524
import com.fasterxml.jackson.databind.util.ClassUtil;
25+
import com.fasterxml.jackson.databind.util.LRUMap;
26+
import com.fasterxml.jackson.dataformat.avro.annotations.AvroNamespace;
2627

2728
public abstract class AvroSchemaHelper
2829
{
@@ -97,8 +98,9 @@ public static boolean isStringable(AnnotatedClass type) {
9798
return false;
9899
}
99100

100-
protected static String getNamespace(JavaType type) {
101-
return getNamespace(type.getRawClass());
101+
protected static String getNamespace(BeanDescription bean) {
102+
AvroNamespace ann = bean.getClassInfo().getAnnotation(AvroNamespace.class);
103+
return ann != null ? ann.value() : getNamespace(bean.getType().getRawClass());
102104
}
103105

104106
protected static String getNamespace(Class<?> cls) {
@@ -244,7 +246,7 @@ public static Schema initializeRecordSchema(BeanDescription bean) {
244246
return addAlias(Schema.createRecord(
245247
getName(bean.getType()),
246248
bean.findClassDescription(),
247-
getNamespace(bean.getType()),
249+
getNamespace(bean),
248250
bean.getType().isTypeOrSubTypeOf(Throwable.class)
249251
), bean);
250252
}
@@ -268,7 +270,7 @@ public static Schema createEnumSchema(BeanDescription bean, List<String> values)
268270
return addAlias(Schema.createEnum(
269271
getName(bean.getType()),
270272
bean.findClassDescription(),
271-
getNamespace(bean.getType()), values
273+
getNamespace(bean), values
272274
), bean);
273275
}
274276

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package com.fasterxml.jackson.dataformat.avro.annotations;
2+
3+
import com.fasterxml.jackson.databind.JsonMappingException;
4+
import com.fasterxml.jackson.dataformat.avro.AvroMapper;
5+
import com.fasterxml.jackson.dataformat.avro.schema.AvroSchemaGenerator;
6+
import org.apache.avro.Schema;
7+
import org.junit.Test;
8+
9+
import static org.assertj.core.api.Assertions.assertThat;
10+
11+
public class AvroNamespaceTest {
12+
13+
static class ClassWithoutAvroNamespaceAnnotation {
14+
}
15+
16+
@AvroNamespace("ClassWithAvroNamespaceAnnotation.namespace")
17+
static class ClassWithAvroNamespaceAnnotation {
18+
}
19+
20+
enum EnumWithoutAvroNamespaceAnnotation {FOO, BAR;}
21+
22+
@AvroNamespace("EnumWithAvroNamespaceAnnotation.namespace")
23+
enum EnumWithAvroNamespaceAnnotation {FOO, BAR;}
24+
25+
@Test
26+
public void class_without_AvroNamespace_test() throws JsonMappingException {
27+
// GIVEN
28+
AvroMapper mapper = new AvroMapper();
29+
AvroSchemaGenerator gen = new AvroSchemaGenerator();
30+
31+
// WHEN
32+
mapper.acceptJsonFormatVisitor(ClassWithoutAvroNamespaceAnnotation.class, gen);
33+
Schema actualSchema = gen.getGeneratedSchema().getAvroSchema();
34+
35+
// THEN
36+
assertThat(actualSchema.getNamespace())
37+
.isEqualTo("com.fasterxml.jackson.dataformat.avro.annotations.AvroNamespaceTest$");
38+
}
39+
40+
@Test
41+
public void class_with_AvroNamespace_test() throws JsonMappingException {
42+
// GIVEN
43+
AvroMapper mapper = new AvroMapper();
44+
AvroSchemaGenerator gen = new AvroSchemaGenerator();
45+
46+
// WHEN
47+
mapper.acceptJsonFormatVisitor(ClassWithAvroNamespaceAnnotation.class, gen);
48+
Schema actualSchema = gen.getGeneratedSchema().getAvroSchema();
49+
50+
// THEN
51+
assertThat(actualSchema.getNamespace())
52+
.isEqualTo("ClassWithAvroNamespaceAnnotation.namespace");
53+
}
54+
55+
@Test
56+
public void enum_without_AvroNamespace_test() throws JsonMappingException {
57+
// GIVEN
58+
AvroMapper mapper = new AvroMapper();
59+
AvroSchemaGenerator gen = new AvroSchemaGenerator();
60+
61+
// WHEN
62+
mapper.acceptJsonFormatVisitor(EnumWithoutAvroNamespaceAnnotation.class, gen);
63+
Schema actualSchema = gen.getGeneratedSchema().getAvroSchema();
64+
65+
// THEN
66+
assertThat(actualSchema.getNamespace())
67+
.isEqualTo("com.fasterxml.jackson.dataformat.avro.annotations.AvroNamespaceTest$");
68+
}
69+
70+
@Test
71+
public void enum_with_AvroNamespace_test() throws JsonMappingException {
72+
// GIVEN
73+
AvroMapper mapper = new AvroMapper();
74+
AvroSchemaGenerator gen = new AvroSchemaGenerator();
75+
76+
// WHEN
77+
mapper.acceptJsonFormatVisitor(EnumWithAvroNamespaceAnnotation.class, gen);
78+
Schema actualSchema = gen.getGeneratedSchema().getAvroSchema();
79+
80+
// THEN
81+
assertThat(actualSchema.getNamespace())
82+
.isEqualTo("EnumWithAvroNamespaceAnnotation.namespace");
83+
}
84+
85+
}

0 commit comments

Comments
 (0)