-
Notifications
You must be signed in to change notification settings - Fork 14
Description
Let's say I have 2 Aerospike Instances
And the Data being saved is
@AerospikeRecord
Class A {
@AerospikeEmbed(type = AerospikeEmbed.EmbedType.LIST)
List<B> b;
}
@AerospikeRecord
Class B {
@AerospikeEmbed(type = AerospikeEmbed.EmbedType.MAP)
private C c
}
Class C {
}
Class C cannot be annotated with @AerospikeRecord due to it being a 3rd party class.
I have 2 instances of Services accessing AerospikeDB where I am able to save using 1 instance and data is getting saved.
But while fetching the data just from 2nd instance it throws NullPointerException at java Object Mapper -> ObjectEmbedMapper.java
Function -> fromAerospikeFormat
ClassCacheEntry<?> entry = ClassCache.getInstance().loadClass(referencedClass, mapper);
try {
switch (type) {
case LIST:
List<Object> listValue = (List<Object>) value;
return entry.constructAndHydrate(listValue, skipKey);
case MAP: // Fall through
case DEFAULT:
return entry.constructAndHydrate((Map<String, Object>) value);
Here the ClassCacheEntry present on Instance 2 does not contain Class C and while loading it since requireRecord is true it returns null since I can't have AerospikeRecord annotation on 3rd party classes. Also on Instance1 when it calls toAerospikeFormat on the same class in that we are using requireRecord to false
The issue being if the ClassCacheEntry is being generated for C on Instance 1 with requireRecord false why is the same Entry not being able to generate on Instance 2 and why do we set requireRecord to true while calling fromAerospike function.
Due to this it is not able to construct the value
toAerospikeFormat call on Instance 1 where requireRecord is false while saving the Data in Instance 1
boolean needsType = !(referencedClass.equals(value.getClass()));
// Use the actual class here in case a subclass is passed. In that case needsType will be true.
ClassCacheEntry<?> entry = ClassCache.getInstance().loadClass(value.getClass(), mapper, false);
// entry would be not null since it would create it as requireRecord is false
switch (type) {
case LIST:
return entry.getList(value, skipKey, needsType);
case MAP: // Fall through
// If unspecified, default to a MAP for embedded objects
case DEFAULT:
return entry.getMap(value, needsType);
fromAerospikeFormat where we force for loading class @AerospikeRecord annotation is not present on Instance 2 while fetching Data
ClassCacheEntry<?> entry = ClassCache.getInstance().loadClass(referencedClass, mapper);
// this returns null entry as in loadClass there is a code that if it is not annotated with @AerospikeRecord it returns null entry so entry.constructAndHydrate fails
try {
switch (type) {
case LIST:
List<Object> listValue = (List<Object>) value;
return entry.constructAndHydrate(listValue, skipKey);
case MAP: // Fall through
case DEFAULT:
return entry.constructAndHydrate((Map<String, Object>) value);