-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AVRO-3968 - [Java] Support for custom @AvroNamespace annotation #2887
base: main
Are you sure you want to change the base?
AVRO-3968 - [Java] Support for custom @AvroNamespace annotation #2887
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change is nicely contained and tested. Well done!
However, it does not implement the annotation as described in Jira (yet). I'm missing the option to override the type name, as the annotation name suggests.
return avroTypeName.value(); | ||
} | ||
if (c.getEnclosingClass() != null) // nested class | ||
return c.getEnclosingClass().getName().replace('$', '.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the enclosing class has an @AvroTypeName?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@opwvhk Thats a great point! I was assuming that we should only be overriding the namespace when the class has the AvroTypeName annotation.
Just to clarify if the class structure is as below:
@AvroTypeName("org.apache.avro.reflect.OverrideNamespace")
private static class NamespaceTest {
private static class EnclosingNamespaceTest {
}
}
When the schema definition is generated for EnclosingNamespaceTest.class, the namespace should be org.apache.avro.reflect.OverrideNamespace ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is now addressed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a reviewer, but have a few questions.
- Classes can be nested further, e.g. a class within a class within a top-level class. Would this method need recursion? Or should only one level of nesting be supported?
- Without the namespace annotation, the namespace of a top-level class is its package, and the namespace of a nested class is package plus name of its enclosing class. In case the enclosing class has the namespace annotation, should its name also be added to the nested namespace in the same way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please find my comments below
-
Classes can be nested further, e.g. a class within a class within a top-level class. Would this method need recursion? Or should only one level of nesting be supported? - To avoid any deviation I have kept the implementation same as the current implementation (without the namespace annotation) which only looks at the immediate top enclosing class for forming the namepsace.
-
Without the namespace annotation, the namespace of a top-level class is its package, and the namespace of a nested class is package plus name of its enclosing class. In case the enclosing class has the namespace annotation, should its name also be added to the nested namespace in the same way? - Thats a valid point. Happy to change if the reviewer suggests so
String space = c.getPackage() == null ? "" : c.getPackage().getName(); | ||
if (c.getEnclosingClass() != null) // nested class | ||
space = c.getEnclosingClass().getName().replace('$', '.'); | ||
String space = getNamespace(c); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would the annotation @AvroTypeName not specify the type name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not clear on this. Could you please explain this?
Do you mean to rename the function getNamespace to getTypeName ?
@Retention(RetentionPolicy.RUNTIME) | ||
@Target({ ElementType.TYPE }) | ||
public @interface AvroTypeName { | ||
String value() default ""; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we always want to specify the name here, or also allow to override the namespace only?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel the responsibility of this annotation should be solely to allow users to override the namespace only given the annotation can only be applied to classes.
@opwvhk regarding your comment -> I'm missing the option to override the type name, as the annotation name suggests. Based on my understanding the ask was the ability to allow overriding the namespace when schema is created using java reflection. The change does this at the moment by removing the default assignment of namepsace which was previously done as below
Kindly let me know if my understanding is incorrect |
Sorry for barging into the discussion uninvited, but I am following this PR, since I like the idea of such an annotation. If I understood the comments on the original issue correctly, then the annotation should not only allow to specify the namespace, but also the name of a record/enum - hence the name
I guess this is what @opwvhk is referring to. On a related note: I really like the idea of this kind of annotation, because namespace & name of a record schema can be independent from package & name of the corresponding class. However, it does not end there: What solved this issue for me was to add a property to the generated schema ( I would appreciate an official solution, so I can throw away my code which may break with new versions of the Avro library. |
@ex-ratt Thanks for your suggestion and your comment was really helpful for me to understand. Regarding you point where we can extend the
When the Person schema is generated, what should the name of the Hence I would rather have @AvroTypeName only applied at class level to only override the namespace. Having thought about its better to rename @AvroTypeName to @AvroNamespace. @opwvhk what are your thoughts on this? Regarding your second point about deserialization failing when using the annotation, that a good point, I l write a testcase to confirm and fix if necessary. |
Actually, With this, I think we should make a choice:
The advantage of option 2 is that this sidesteps this entire discussion, but it also means there are 2 annotations to adjust the full type name. The latter is what will stay with us forever. The advantage of option 3 is that we don't have two annotations on full type names, but I'm not happy with the extra syntax. |
I prefer the option 2 where I dont think option 3 works too well because If we agree that option 2 is the best course of action to implement this feature, then the current code anyways does that today with the only difference being the name of the annotation is @opwvhk if thats fine I l just update the name to |
Hi @opwvhk. Kind reminder. Awaiting your response so I can make the changes required |
Although I really prefer option 1, I can also live with option 2. Can you please make the changes for |
@opwvhk I have made the changes discussed
Kindly request you to review |
@opwvhk awaiting you review |
Awaiting review on this |
Add support for custom AvroTypeName annotation to allow overriding namespace when generating schema with reflection
What is the purpose of the change
Add support for custom AvroTypeName annotation to allow overriding namespace when generating schema with reflection
Verifying this change
This change added tests and can be verified as follows:
Documentation