Skip to content

[3.2.0][BUG] Entities with fields of types from other packages leads to "MapperExcpeption: Parameter does not have a name" #4615

Closed as not planned
@Nevac

Description

@Nevac

Description of the issue

If an entity contains a field of some type which is defined in another package, a mapping exception will be thrown during a read operation if said object doesn't provide an empty constructor (private, protected or public). Retrofitting all our classes with an empty constructor can't be a feasible solution.

This exception happens since Spring Boot 3.2.0 and is not present in version 3.1.5, which suggest a possible regression.

Example

All code snippets are taken from the example project to reproduce this issue, which can be found here:
https://gitlab.com/elderbyte/public/examples/spring-mongo-mapping-param-noname-issue

Project contains two packages:

  • com.mappingissue.app - Spring Boot Application
  • com.mappingissue.other - Package that contains some objects

Class Cat and Collar are defined in com.mappingissue.app package.
Class CollarLib is defined in com.mappingissue.other packege.

  • app
    -- Cat
    -- Collar
  • other
    -- CollarLib

Class Cat is used to persist and read data from the DB (Cat document).
Class Cat contains a field of type Collar and a field of type CollarLib.
Both Collar and CollarLib have the same fields, String id and String company

Cat.class com.mappingissue.app

@Document
public class Cat {

    @Id
    private String id;
    private String name;
    private Collar collar;
    private CollarLib collarLib;
    
    ...
}   

Collar.class com.mappingissue.app

public class Collar {
    private String id;
    private String company;
    ...
}

CollarLib.class com.mappingissue.other

public class CollarLib {
    private String id;
    private String company;
    ...
}

When a Cat with a existing (non null) CollarLib is read, the MappingException is thrown.

Hence, for following tests, success() will pass but fail_MappingException_ParameterDoesNotHaveAName will fail with exception (Stack traced can be found at the end of the issue):

    @Test
    public void success() {
        mongoOperations.save(
                new Cat(
                        "1",
                        "Sir Meow",
                        new Collar("John Doe", "123 Fake Street"),
                        null
                )
        );
        var cat = mongoOperations.find(
                Query.query(
                        Criteria.where("id").is("1")
                ),
                Cat.class
        ).get(0);

        Assertions.assertEquals("1", cat.getId());
    }

    @Test
    public void fail_MappingException_ParameterDoesNotHaveAName() {
        mongoOperations.save(
                new Cat(
                        "2",
                        "Lady Purr",
                        new Collar("1", "Collar Inc"),
                        new CollarLib("1", "Collar Inc")
                )
        );
        var cat = mongoOperations.find(
                Query.query(
                        Criteria.where("id").is("2")
                ),
                Cat.class
        ).get(0);

        Assertions.assertEquals("2", cat.getId());

    }

The issue is resolved if CollarLib in the com.mappingissue.other provides an empty constructor

Used versions

Spring Boot: 3.2.1
Java: openjdk version "17.0.5" 2022-10-18 LTS
MongoDB: 6.0.3

Example project for reproduction

https://gitlab.com/elderbyte/public/examples/spring-mongo-mapping-param-noname-issue

Stacktrace from example project

org.springframework.data.mapping.MappingException: Parameter org.springframework.data.mapping.Parameter@c84af0a8 does not have a name
   at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:61 undefined)
   at org.springframework.data.mapping.model.SpELExpressionParameterValueProvider.getParameterValue(SpELExpressionParameterValueProvider.java:49 undefined)
   at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.extractInvocationArguments(ClassGeneratingEntityInstantiator.java:301 undefined)
   at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator$EntityInstantiatorAdapter.createInstance(ClassGeneratingEntityInstantiator.java:273 undefined)
   at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:98 undefined)
   at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:519 undefined)
   at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readDocument(MappingMongoConverter.java:487 undefined)
   at org.springframework.data.mongodb.core.MappingMongoConverter$DefaultConversionContext.convert.convert(MappingMongoConverter.java:2366 undefined)
   at org.springframework.data.mongodb.core.MappingMongoConverter$ConversionContext.convert.convert(MappingMongoConverter.java:2175 undefined)
   at org.springframework.data.mongodb.core.convert.MappingMongoConverter$MongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1941 undefined)
   at org.springframework.data.mongodb.core.convert.MappingMongoConverter$AssociationAwareMongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:2000 undefined)
   at org.springframework.data.mongodb.core.convert.MappingMongoConverter$AssociationAwareMongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1959 undefined)
   at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:71 undefined)
   at org.springframework.data.mapping.model.SpELExpressionParameterValueProvider.getParameterValue(SpELExpressionParameterValueProvider.java:49 undefined)
   at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.extractInvocationArguments(ClassGeneratingEntityInstantiator.java:301 undefined)
   at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator$EntityInstantiatorAdapter.createInstance(ClassGeneratingEntityInstantiator.java:273 undefined)
   at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:98 undefined)
   at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:519 undefined)
   at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readDocument(MappingMongoConverter.java:487 undefined)
   at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:423 undefined)
   at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:419 undefined)
   at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:119 undefined)
   at org.springframework.data.mongodb.core.MongoTemplate$ReadDocumentCallback.doWith(MongoTemplate.java:3278 undefined)
   at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:2912 undefined)
   at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:2592 undefined)
   at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:2573 undefined)
   at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:866 undefined)
   at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:856 undefined)
   at com.elderbyte.mappingissue.app.ApplicationTest.fail_MappingException_ParameterDoesNotHaveAName(ApplicationTest.java:58 undefined)
   at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77 undefined)
   at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43 undefined)
   at java.base/java.lang.reflect.Method.invoke(Method.java:568 undefined)
   at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:728 undefined)
   at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60 undefined)
   at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131 undefined)
   at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156 undefined)
   at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147 undefined)
   at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86 undefined)
   at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103 undefined)
   at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93 undefined)
   at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106 undefined)
   at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64 undefined)
   at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45 undefined)
   at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37 undefined)
   at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92 undefined)
   at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86 undefined)
   at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:218 undefined)
   at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73 undefined)
   at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:214 undefined)
   at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:139 undefined)
   at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:69 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151 undefined)
   at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141 undefined)
   at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139 undefined)
   at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95 undefined)
   at java.base/java.util.ArrayList.forEach(ArrayList.java:1511 undefined)
   at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155 undefined)
   at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141 undefined)
   at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139 undefined)
   at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95 undefined)
   at java.base/java.util.ArrayList.forEach(ArrayList.java:1511 undefined)
   at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155 undefined)
   at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141 undefined)
   at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139 undefined)
   at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95 undefined)
   at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35 undefined)
   at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57 undefined)
   at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54 undefined)
   at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107 undefined)
   at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88 undefined)
   at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54 undefined)
   at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67 undefined)
   at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52 undefined)
   at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114 undefined)
   at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86 undefined)
   at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86 undefined)
   at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:119 undefined)
   at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:94 undefined)
   at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:89 undefined)
   at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:62 undefined)
   at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77 undefined)
   at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43 undefined)
   at java.base/java.lang.reflect.Method.invoke(Method.java:568 undefined)
   at org.gradle.internal.ReflectionDispatch.dispatch.dispatch(ReflectionDispatch.java:36 undefined)
   at org.gradle.internal.ReflectionDispatch.dispatch.dispatch(ReflectionDispatch.java:24 undefined)
   at org.gradle.internal.ContextClassLoaderDispatch.dispatch.dispatch(ContextClassLoaderDispatch.java:33 undefined)
   at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94 undefined)
   at jdk.proxy1/jdk.proxy1.$Proxy2.stop(Unknown Source)
   at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193 undefined)
   at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129 undefined)
   at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100 undefined)
   at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60 undefined)
   at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56 undefined)
   at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113 undefined)
   at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65 undefined)
   at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69 undefined)
   at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74 undefined)

Metadata

Metadata

Labels

status: invalidAn issue that we don't feel is valid

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions