Skip to content

NullPointerException in Aerospike when using 2 Instances of Service #146

@KalshuCodes

Description

@KalshuCodes

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);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions