[
https://issues.apache.org/jira/browse/AVRO-2723?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17032099#comment-17032099
]
Anh Le commented on AVRO-2723:
------------------------------
[~rskraba]
h4. Usecase
My use case is:
* I want to develop a standalone server for registering/storing Avro schemas,
including default values
* Applications (Java first) can freely register schemas. They can easily do
that by having a `middleware` library to inspect POJO objects into Avro Schema
h4. Feedbacks
> If you have a POJO instance and you want to get the default for a field, you
> can use plain Java: *{{new User().first}}*
I know. But from the server's view, it just see Avro schema, right?
> ... you can add an *{{@AvroDefault}}* annotation to the field [like this unit
> test|https://github.com/apache/avro/blob/70260919426f89825ca148f5ee815f3b2cf4764d/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java#L1262].
> ...
I see the code. It works!
{code:java}
class User {
@AvroDefault("40")
public int age;
}
{code}
But I think there are several drawbacks for this approach
1. It's a less natural way compared to the following:
{code:java}
class User {
public int age = 40;
}
{code}
2. Fields can't be non-primitive objects (I
For example, this will yield exception
{code:java}
class User {
@AvroDefault(value = "40")
public Integer age;
}
{code}
This also result in #1 if we have a complicated class.
h4. Solution
I've hacked into Avro code base and see a solution
- Refactor: ReflectData.createSchema() (lines
[#L617-L627|https://github.com/apache/avro/blob/master/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java#L617-L627]
to have an overridable function named as `getDefaultValue()`
- I then can derive ReflectData class to provide the default values:
{code:java}
class DefaultReflector extends ReflectData {
private static final ReflectData INSTANCE = new DefaultReflector();
/** Return the singleton instance. */
public static ReflectData get() {
return INSTANCE;
}
@Override
protected Object getDefaultValue(Type type, Schema fieldSchema, Field field) {
try {
String className = ((Class) type).getName();
Object val = Class.forName(className).newInstance();
return field.get(val);
} catch (Exception e) {
e.printStackTrace();
return super.getDefaultValue(type, fieldSchema, field);
}
}
@Override
protected Schema createFieldSchema(Field field, Map<String, Schema> names) {
Schema schema = super.createFieldSchema(field, names);
if (field.getType().isPrimitive()) {
// for primitive values, such as int, a null will result in a
// NullPointerException at read time
return schema;
}
return makeNullable(schema);
}
}
{code}
h4. Question
- Is there any solution for my use case?
- Should I make a PR to refactor ReflectData to have `getDefaultValue`
overridable in derived classes ?
> Avro Java: Obtaining default values for POJO objects with ReflectData
> ---------------------------------------------------------------------
>
> Key: AVRO-2723
> URL: https://issues.apache.org/jira/browse/AVRO-2723
> Project: Apache Avro
> Issue Type: Wish
> Components: java
> Affects Versions: 1.9.1
> Reporter: Anh Le
> Priority: Critical
>
> Hi guys,
>
> I've got a simple app using Avro Reflection:
>
> {code:java}
> public class App {
> public static void main(String[] args) {
> testReflection();
> }
> static class User {
> public String first = "Andy";
> public String last = "Le";
> }
> static void testReflection(){
> // get the reflected schema for packets
> Schema schema = ReflectData.AllowNull.get().getSchema(User.class);
> System.out.println(schema.toString(true));
> }
> {code}
> The output on console will be:
> {noformat}
> {
> "type" : "record",
> "name" : "User",
> "namespace" : "App",
> "fields" : [ {
> "name" : "first",
> "type" : [ "null", "string" ],
> "default" : null
> }, {
> "name" : "last",
> "type" : [ "null", "string" ],
> "default" : null
> } ]
> }
> {noformat}
>
> As you can see, there's no default values for fields. Would you please tell
> me how to obtain such values?
> Thank you.
>
>
>
>
>
--
This message was sent by Atlassian Jira
(v8.3.4#803005)