Skip to content

[3.2.1] Indexing Class with Custom Converter -> Couldn't find PersistentEntity for property private [...] #3659

Closed
@IsNull

Description

@IsNull

We updated from spring boot 2.4.2 to 2.5.0, and now Index creation is broken. This means the same code that worked before wont under 2.5.0. (spring-data-mongodb 3.1.3 to 3.2.1 )


I have created a sample Project which shows the problem: https://gitlab.com/elderbyte/public/examples/spring-mongo-index-issue


Creating an mongo index fails, when the dot path notation is used and the referenced class is in a separate library has a custom mongo converter:

@Configuration
@EnableMongoRepositories()
public class DefaultMongoConfiguration {


    @Bean
    public MongoCustomConversions customConversions(){
        var converters = new ArrayList<Converter<?,?>>();
        converters.add(new MyAddressToDocumentConverter()); // Comment this out, and it works
        return new MongoCustomConversions(converters);
    }

    @WritingConverter
    public static class MyAddressToDocumentConverter implements Converter<MyAddress, Document> {
        @Override
        public Document convert(MyAddress address) {
            var doc = new Document();
            doc.put("street", address.getStreet());
            return doc;
        }
    }
}

The entity for which this index is being defined looks like this (simplified):

@Document
public class Customer {

    @Id
    private ObjectId id;

    private String name;

    private MyAddress address;

}
public class MyAddress {

    private String street;

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }
}

Creating an Index via ensure index yields an unexpected exception:

        indexOps.ensureIndex(
                TextIndexDefinition
                        .builder()
                        .named("TextIndex")
                        .onField("name")
                        .onField("address.street")
                        .build()
        );

Stacktrace

org.springframework.data.mapping.MappingException: Couldn't find PersistentEntity for property private com.elderbyte.starter.demo.domain.customers.MyAddress com.elderbyte.starter.demo.domain.customers.Customer.address!
	at org.springframework.data.mapping.context.MappingContext.getRequiredPersistentEntity(MappingContext.java:152) ~[spring-data-commons-2.5.1.jar:2.5.1]
	at org.springframework.data.mapping.context.PersistentPropertyPathFactory.getPair(PersistentPropertyPathFactory.java:225) ~[spring-data-commons-2.5.1.jar:2.5.1]
	at org.springframework.data.mapping.context.PersistentPropertyPathFactory.createPersistentPropertyPath(PersistentPropertyPathFactory.java:199) ~[spring-data-commons-2.5.1.jar:2.5.1]
	at org.springframework.data.mapping.context.PersistentPropertyPathFactory.lambda$getPersistentPropertyPath$1(PersistentPropertyPathFactory.java:172) ~[spring-data-commons-2.5.1.jar:2.5.1]
	at java.base/java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:330) ~[na:na]
	at org.springframework.data.mapping.context.PersistentPropertyPathFactory.getPersistentPropertyPath(PersistentPropertyPathFactory.java:171) ~[spring-data-commons-2.5.1.jar:2.5.1]
	at org.springframework.data.mapping.context.PersistentPropertyPathFactory.from(PersistentPropertyPathFactory.java:86) ~[spring-data-commons-2.5.1.jar:2.5.1]
	at org.springframework.data.mapping.context.PersistentPropertyPathFactory.from(PersistentPropertyPathFactory.java:99) ~[spring-data-commons-2.5.1.jar:2.5.1]
	at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentPropertyPath(AbstractMappingContext.java:285) ~[spring-data-commons-2.5.1.jar:2.5.1]
	at org.springframework.data.mongodb.core.convert.QueryMapper$MetadataBackedField.getPath(QueryMapper.java:1183) ~[spring-data-mongodb-3.2.1.jar:3.2.1]
	at org.springframework.data.mongodb.core.convert.QueryMapper$MetadataBackedField.<init>(QueryMapper.java:1045) ~[spring-data-mongodb-3.2.1.jar:3.2.1]
	at org.springframework.data.mongodb.core.convert.QueryMapper$MetadataBackedField.<init>(QueryMapper.java:1022) ~[spring-data-mongodb-3.2.1.jar:3.2.1]
	at org.springframework.data.mongodb.core.convert.QueryMapper.createPropertyField(QueryMapper.java:329) ~[spring-data-mongodb-3.2.1.jar:3.2.1]
	at org.springframework.data.mongodb.core.convert.QueryMapper.getMappedSort(QueryMapper.java:197) ~[spring-data-mongodb-3.2.1.jar:3.2.1]
	at org.springframework.data.mongodb.core.DefaultIndexOperations.lambda$ensureIndex$0(DefaultIndexOperations.java:130) ~[spring-data-mongodb-3.2.1.jar:3.2.1]
	at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:553) ~[spring-data-mongodb-3.2.1.jar:3.2.1]
	at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:539) ~[spring-data-mongodb-3.2.1.jar:3.2.1]
	at org.springframework.data.mongodb.core.DefaultIndexOperations.execute(DefaultIndexOperations.java:211) ~[spring-data-mongodb-3.2.1.jar:3.2.1]
	at org.springframework.data.mongodb.core.DefaultIndexOperations.ensureIndex(DefaultIndexOperations.java:121) ~[spring-data-mongodb-3.2.1.jar:3.2.1]
	at com.elderbyte.starter.demo.domain.customers.CustomerIndexConfiguration.initIndicesAfterStartup(CustomerIndexConfiguration.java:54) ~[main/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
	at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:344) ~[spring-context-5.3.7.jar:5.3.7]
	at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:229) ~[spring-context-5.3.7.jar:5.3.7]
	at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:166) ~[spring-context-5.3.7.jar:5.3.7]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176) ~[spring-context-5.3.7.jar:5.3.7]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169) ~[spring-context-5.3.7.jar:5.3.7]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143) ~[spring-context-5.3.7.jar:5.3.7]
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:421) ~[spring-context-5.3.7.jar:5.3.7]
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:378) ~[spring-context-5.3.7.jar:5.3.7]
	at org.springframework.boot.context.event.EventPublishingRunListener.running(EventPublishingRunListener.java:111) ~[spring-boot-2.5.0.jar:2.5.0]
	at org.springframework.boot.SpringApplicationRunListeners.lambda$running$6(SpringApplicationRunListeners.java:79) ~[spring-boot-2.5.0.jar:2.5.0]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) ~[na:na]
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:117) ~[spring-boot-2.5.0.jar:2.5.0]
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:111) ~[spring-boot-2.5.0.jar:2.5.0]
	at org.springframework.boot.SpringApplicationRunListeners.running(SpringApplicationRunListeners.java:79) ~[spring-boot-2.5.0.jar:2.5.0]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:352) ~[spring-boot-2.5.0.jar:2.5.0]
	at com.elderbyte.starter.demo.MongodbDemoServer.main(MongodbDemoServer.java:21) ~[main/:na]

2021-05-27 10:59:59.330  INFO 9895 --- [           main] o.s.b.a.ApplicationAvailabilityBean      : Application availability state ReadinessState changed to REFUSING_TRAFFIC
2021-05-27 10:59:59.358  INFO 9895 --- [           main] org.mongodb.driver.connection            : Closed connection [connectionId{localValue:3, serverValue:840}] to localhost:27017 because the pool has been closed.

Process finished with exit code 1

Conclusions:

  • We observed the problem first with Spring Boot 2.5.0 which uses the version 3.2.1 of spring-data-mongodb
    • Therefore it looks like a regression from Spring Boot 2.4.2 where the same code works (3.1.3 of spring-data-mongodb)
    • Edit: Spring Boot 2.4.6 also works (3.1.9 spring-data-mongodb)
  • The class com.elderbyte.commons.i18n.I18nText is in another library which is a gradle (maven) dependency.
  • Repository Base package has been set to com.elderbyte so it should include both classes
  • If I copy the class from that library into the local project, it works.
  • It seems to be caused by the custom converter.
  • If the custom converter is not registered, it works.

Any idea what could have caused this and how to fix it?

Metadata

Metadata

Labels

type: regressionA regression from a previous release

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions