Cannot read enum property, ClassCastException

78
March 05, 2021, at 02:20 AM

For my model I have problem with reading enum property. After reading from mongoDB, the property 'value' has type String instead of MyEnum.

My model:

public class Record {
    @Id
    public String id;
    public Wrapper<MyEnum> wrappedEnum;
   ...
}
public class Wrapper<T extends Enum<?>> extends BaseWrapper<T>{
    ...
}
public class BaseWrapper<T> {
    public T value;
    ...
}

Code:

 Record record = new Record();
        Wrapper<MyEnum> wrapper = new Wrapper<>();
        wrapper.setValue(MyEnum.A);
        record.setWrappedEnum(wrapper);
        repository.save(record);

        repository.findAll().forEach(rec -> {
            Object value = rec.getWrappedEnum().value;
            System.out.println("rec.getWrappedEnum().value: " + value); // rec.getWrappedEnum().value: A
            System.out.println("rec.getWrappedEnum().getValue(): " + value.getClass()); // rec.getWrappedEnum().getValue(): class java.lang.String
            MyEnum valEnum = rec.getWrappedEnum().getValue(); // throws Caused by: java.lang.ClassCastException: class java.lang.String cannot be cast to class com.example.MyEnum (java.lang.String is in module java.base of loader 'bootstrap'; com.example.MyEnum is in unnamed module of loader 'app')
        });

Is any option to configure mongodb to read this model correctly?

Answer 1

The reason why you are getting a ClassCastException is because you didn't specify how the persistence layer should actually persist your wrapped enum.

I suppose you are using JPA as the persistence API. There are actually multiple ways to achieve what you want. The more convenient way for your case would be to register a converter, so that JPA knows how to persist your Enum and map it back. A basic example could look like this (Note that there are setter for the value field in BaseWrapper):

@Converter
public class WrapperConverter implements AttributeConverter<Wrapper, String> {
  @Override
  public String convertToDatabaseColumn(Wrapper attribute) {
    return attribute.getValue().toString();
  }
  @Override
  public Wrapper convertToEntityAttribute(String dbData) {
    MyEnum myEnum = MyEnum.valueOf(dbData);
    Wrapper<MyEnum> wrappedEnum = new Wrapper<>();
    wrappedEnum.setValue(myEnum);
    return wrappedEnum;
  }
}

Register the converter:

@Entity
public class Record {
  @Id
  private String id;
  @Convert(converter = WrapperConverter.class)
  private Wrapper<MyEnum> wrappedEnum;
READ ALSO
How to get answers in a random order with handlebars?

How to get answers in a random order with handlebars?

i created a quiz App with NodeJs, storing the questions and answers in MongoDb and using Hanbldebars but i ran into a problemThe code works fine but as you can see the correct answer to the questions appears always in the first place, making the game totally...

61
JavaScript filter array of objects based on property values

JavaScript filter array of objects based on property values

I have an array of objects in javascriptThe contents look like this;

60
How to kill a query running by pd.read_sql and connected by sqlalchemy (or mysql.connector)

How to kill a query running by pd.read_sql and connected by sqlalchemy (or mysql.connector)

I have a Python API that receives a request from PHP code and executes some queries with pdread_sql() in a MariaDB 10

66