javamongodbspring-bootmongodb-querymongotemplate

MappingInstantiationException from MongoDB while trying to update a collection with an abstract class


So I'm having this issue where I'm using a single collection to store different classes that inherit from the same abstract class wrapped in another class. I can insert these records without issue, but when I need to update a common property it fails. What can I do in this case?

Error:

"Failed to instantiate com.models.Task using constructor public com.models.Task() with arguments "

Classes:

//wrapper
@Data
@Document(collection="tasks")
public class WrapperTask {
    @Id
    private ObjectId id;
    @BsonProperty(useDiscriminator = true)
    private Task task;

    public WrapperTask() {
    }

    public String getId() {
        return Utils.ObjectId(this.id);
    }
}

//abstract
@Data
@JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({ 
    @Type(value = UploadTask.class, name = "uploadTask"),
    //more classes
})
@BsonDiscriminator
public abstract class Task {
    private TaskStatus status;
    public int totalCount;
    public int completedCount;

    public Task() {
        this.status = TaskStatus.NEW;
    }
}

//child
@Data
@EqualsAndHashCode(callSuper = true)
@Document(collection = "tasks")
@TypeAlias("uploadTask")
@BsonDiscriminator
public class UploadTask extends Task {

    private LinkedList<Document> documents = new LinkedList<>();

    public UploadTask(int totalCount) {
        super();
        this.totalCount = totalCount;
    }

    public UploadTask() {
        super();
    }
}

Logic:

Query query = new Query(Criteria.where("_id").is(taskId));
Update update = new Update();
update = update.set("task.status", "some status");
    
if (taskType == UploadTask.class) {
    Criteria criteria = Criteria.where("document.index").is(index);           
    update = update.set("task.documents.$[document].status", "some status");
    update = update.set("task.documents.$[document].statusMessage", "some message").filterArray(criteria);    
}

mongoOperations.findAndModify(query, update, options().upsert(false), WrapperTask.class);

So, how do I make this update work?

Thanks


Solution

  • As suggested in this post, the answer is to override the getMappingBasePackages() in the mongo config file:

    @Override
    protected Collection<String> getMappingBasePackages()
    {
        return Arrays.asList("com.myapp.models");
    }