spring-data-mongodb
spring-data-mongodb copied to clipboard
ClassCastException when using PropertyValueConverter with generic types
Dear friends,
On our project we faced with issue when using PropertyValueConverter
that cause ClassCastException
.
Here are some code snippets:
Entity class with ValueConverter annotation:
@Document("user")
@Data
public class User {
@ValueConverter(WriteInLowerCase.class)
private String email;
}
Converter implementation:
public class WriteInLowerCase implements PropertyValueConverter<String, String, ValueConversionContext<?>> {
@Override
public String read(String value, ValueConversionContext<?> context) {
return value;
}
@Override
public String write(String value, ValueConversionContext<?> context) {
return value.toLowerCase();
}
}
And SpringData repository:
@Repository
public interface UserRepository extends MongoRepository<User, String> {
List<AccessEntity> findAllByEmailIgnoreCase(String email);
}
After calling findAllByEmailIgnoreCase
we got and exception:
java.lang.ClassCastException: class java.util.regex.Pattern cannot be cast to class java.lang.String (java.util.regex.Pattern and java.lang.String are in module java.base of loader 'bootstrap')
at com.epam.adminpanel.repo.mongo.converter.WriteInLowerCase.write(WriteInLowerCase.java:6) ~[main/:na]
at org.springframework.data.mongodb.core.convert.QueryMapper.getMappedValue(QueryMapper.java:440) ~[spring-data-mongodb-4.0.0.jar:4.0.0]
at org.springframework.data.mongodb.core.convert.QueryMapper.getMappedObjectForField(QueryMapper.java:337) ~[spring-data-mongodb-4.0.0.jar:4.0.0]
at org.springframework.data.mongodb.core.convert.QueryMapper.getMappedObject(QueryMapper.java:164) ~[spring-data-mongodb-4.0.0.jar:4.0.0]
at org.springframework.data.mongodb.core.QueryOperations$QueryContext.getMappedQuery(QueryOperations.java:348) ~[spring-data-mongodb-4.0.0.jar:4.0.0]
at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:2463) ~[spring-data-mongodb-4.0.0.jar:4.0.0]
at org.springframework.data.mongodb.core.ExecutableFindOperationSupport$ExecutableFindSupport.doFind(ExecutableFindOperationSupport.java:171) ~[spring-data-mongodb-4.0.0.jar:4.0.0]
at org.springframework.data.mongodb.core.ExecutableFindOperationSupport$ExecutableFindSupport.all(ExecutableFindOperationSupport.java:134) ~[spring-data-mongodb-4.0.0.jar:4.0.0]
at org.springframework.data.mongodb.repository.query.AbstractMongoQuery.lambda$getExecution$3(AbstractMongoQuery.java:169) ~[spring-data-mongodb-4.0.0.jar:4.0.0]
at org.springframework.data.mongodb.repository.query.AbstractMongoQuery.doExecute(AbstractMongoQuery.java:143) ~[spring-data-mongodb-4.0.0.jar:4.0.0]
at org.springframework.data.mongodb.repository.query.AbstractMongoQuery.execute(AbstractMongoQuery.java:118) ~[spring-data-mongodb-4.0.0.jar:4.0.0]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:136) ~[spring-data-commons-3.0.0.jar:3.0.0]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:120) ~[spring-data-commons-3.0.0.jar:3.0.0]
......
The solution from our side was to update implementation of WriteInLowerCase
to be without generic implementation:
public class WriteInLowerCase implements PropertyValueConverter {
@Override
public Object read(Object value, ValueConversionContext context) {
return value;
}
@Override
public Object write(Object value, ValueConversionContext context) {
if (value instanceof String stringValue) {
return stringValue.toLowerCase();
}
return value;
}
}
But I believe, that types should not be ignored.
Thanks for reporting! That's an interesting one since the PartTreeMongoQuery
will create a BsonRegularExpression
for IgnoreCase
which then violates the PropertyValueConverter
.
Will take it to the team.
Ideally, we fix the issue initially on the converter level by checking whether the value is assignable to the property type.
Going forward, if we capture values in other types (e.g. create a Pattern
from a String
), we should investigate whether we can apply conversions before the Pattern
is created.
Thanks for reporting @MrHurniak. I ran into this same problem and using the broader Object
is working for now.