aerospike / java-object-mapper

The Java Object Mapper is a simple, light-weight framework used to map POJOs to the Aerospike database. Using simple annotations or a configuration YAML file to describe how to map the data to Aerospike, the project takes the tedium out of mapping the data through the powerful, low level interface.
Apache License 2.0
18 stars 13 forks source link

Why do we need the classes to implement serializable #118

Closed Agrawalmahin closed 1 year ago

Agrawalmahin commented 2 years ago
@Record
public class A {
  @Key
  private String id;
  @Embed...
  public List<B> bList;
}

public class B {
  @Embed ....
   public List<C> cList
}

public class C {
    public String s1;
    public String s2;
}

If at class C, we donot implement the serializable interface, then this throw -10 client error stating it is not able to serialize class C. What is the need for implementing serializable interface?

reugn commented 2 years ago

@Agrawalmahin, add the @AerospikeRecord annotation to the B and C classes.

Agrawalmahin commented 2 years ago

Thanks this worked, we need to add it to all the classes, even if it is abstract, child, all the classes 😢 , just a thought, why do we need to do this? shouldn't the child class's annotations work?

Agrawalmahin commented 2 years ago

Hi @reugn request you to please help me with an answer to the above question

Thanks in advance!

tfaulkes commented 2 years ago

The reason is to do with knowing where the hierarchy we need to serialize into Aerospike stops. Imagine there was no constraint, and every superclass of a class marked with @AerospikeRecord was assumed to have all the fields serializable into the database.

An innocuous class suddenly yields surprise fields:

@AerospikeRecord
public class A extends java.util.Date {
   public String name;
}

In this case, you would not only get name field, but all the attributes of the Date superclass, including defaultCenturyStart, jCal, gCal (until recently) and other internal workings. These are clearly not desirable to be mapped to the database. Given mapAll is set to true by default and introspection is used by the object mapper to be able to map even private fields, allowing unchecked access to the whole hierarchy of superclasses would be dangerous.

Marking the superclass with @AerospikeRecord is really just saying to the object mapper "this class is safe to serialize to the database".

It may be more tractable to automatically have any subclasses of a class annotated with @AerospikeRecord automatically inherit the annotation. This would mean all subclasses would roll up to the same Aerospike Set and might have performance implications as each class would need to check for an annotation on all superclasses. Is adding @AerospikeRecord to each class really a significant issue for you? If so, can you please provide some details as to why?

reugn commented 2 years ago

@tfaulkes let me know your thoughts on #125.

Agrawalmahin commented 2 years ago

Is adding @AerospikeRecord to each class really a significant issue for you? If so, can you please provide some details as to why? Yes it is an issue, Assume I am using a 3rd party library, and extending one of the classes, and want to store their private fields as well within our record, I would not be able to do so, because I cannot ask them to add @AerosikeRecord . So the only option that remains with me, is to clone the class in my code base and work with that, and that does not sound to be a correct approach. Do let me know if any one has faced a problem like this, we can discuss more on this!

reugn commented 2 years ago

@Agrawalmahin see version 2.1.0. It takes time to sync to Maven Central.

tfaulkes commented 2 years ago

Ah, that makes sense. Yes, external libraries that you extend obviously cannot be annotated. Thanks to the good work from @reugn and others, there are now 2 ways of addressing this:

Of the 2, the external configuration file is the more flexible, but requires more work to set up vs the simpler implementation in 2.1.0.

withConfigurationFile: Whilst mapping information from POJOs via annotations is efficient and has the mapping code inline with the POJO code, there are times when this is not available. For example, if an external library with POJOs is being used and it is desired to map those POJOs to the database, there is no easy way of annotating the source code.

reugn commented 1 year ago

@Agrawalmahin feel free to reopen if you have further questions about this.

Agrawalmahin commented 1 year ago

Hello

@Record
public class A {
  @Key
  private String id;
  @Embed...
  public List<B> bList;
}

public class B {
    @Bin...
   public C c;
}

public class C {
    public String s1;
    public String s2;

    @Embed..
    public List<D> dList;
}

public class D {

    public String s3;

}

classes C and D are external. C and D do not implement serializable.

we are getting not serializable exception.

If the above is solved, will current case also be solved?

using aero-mapper-version : 2.2.0