Exception when mapping non existing target.. #1153

Closed
sjaakd opened this Issue Mar 23, 2017 · 3 comments

Comments

Projects
None yet
3 participants
@sjaakd
Contributor

sjaakd commented Mar 23, 2017

Internal error in the mapping processor: java.util.NoSuchElementException at
 java.util.ArrayList$Itr.next(ArrayList.java:854)  	at
 org.mapstruct.ap.internal.util.Collections.first(Collections.java:77)  	at
 org.mapstruct.ap.internal.model.NestedTargetPropertyMappingHolder$Builder.groupByTargetReferences(NestedTargetPropertyMappingHolder.java:288)  	at
 org.mapstruct.ap.internal.model.NestedTargetPropertyMappingHolder$Builder.build(NestedTargetPropertyMappingHolder.java:133)  	at
 org.mapstruct.ap.internal.model.BeanMappingMethod$Builder.handleDefinedNestedTargetMapping(BeanMappingMethod.java:359)  	at
 org.mapstruct.ap.internal.model.BeanMappingMethod$Builder.handleDefinedMappings(BeanMappingMethod.java:325)  	at
 org.mapstruct.ap.internal.model.BeanMappingMethod$Builder.build(BeanMappingMethod.java:137)  	at
 org.mapstruct.ap.internal.processor.MapperCreationProcessor.getMappingMethods(MapperCreationProcessor.java:373)  	at
 org.mapstruct.ap.internal.processor.MapperCreationProcessor.getMapper(MapperCreationProcessor.java:152)  	at
 org.mapstruct.ap.internal.processor.MapperCreationProcessor.process(MapperCreationProcessor.java:123)  	at
 org.mapstruct.ap.internal.processor.MapperCreationProcessor.process(MapperCreationProcessor.java:80)  	at
 org.mapstruct.ap.MappingProcessor.process(MappingProcessor.java:280)  	at
 org.mapstruct.ap.MappingProcessor.processMapperTypeElement(MappingProcessor.java:260)  	at
 org.mapstruct.ap.MappingProcessor.processMapperElements(MappingProcessor.java:226)  	at
 org.mapstruct.ap.MappingProcessor.process(MappingProcessor.java:162)  	at
 com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794)  	at
 com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705)  	at
 com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91)  	at
 com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035)  	at
 com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176)  	at
 com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)  	at
 com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856)  	at
 com.sun.tools.javac.main.Main.compile(Main.java:523)  	at
 com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)  	at
 com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138)  	at
 org.codehaus.plexus.compiler.javac.JavaxToolsCompiler.compileInProcess(JavaxToolsCompiler.java:125)  	at
 org.codehaus.plexus.compiler.javac.JavacCompiler.performCompile(JavacCompiler.java:171)  	at
 org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:886)  	at
 org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.java:129)  	at
 org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)  	at
 org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)  	at
 org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)  	at
 org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)  	at
 org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)  	at
 org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)  	at
 org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)  	at
 org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)  	at
 org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)  	at
 org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)  	at
 org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)  	at
 org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)  	at
 org.apache.maven.cli.MavenCli.main(MavenCli.java:141)  	at
 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  	at
 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)  	at
 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)  	at
 java.lang.reflect.Method.invoke(Method.java:498)  	at
 org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)  	at
 org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)  	at
 org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)  	at
 org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)  

Problem occurs when a nested property is accessed on target side which does not exist.

@filiphr

This comment has been minimized.

Show comment
Hide comment
@filiphr

filiphr Apr 18, 2017

Member

@mgohin unfortunately there won't be any debug information in the console. Hint for us: Maybe add some more verbose info to display which method is being mapped.

The best way to find out what is happening is to run the compilation in debug mode. I am not sure what you use as your IDE or your build tool. For me with IntelliJ and Maven I run the compile goal with debug and you can find out. You can either break when the NoSuchElementException occurs or in the NestedTargetPropertyMappingHolder at line 288. When you are there see the method in the NestedTargetPropertyMappingHolder. Depending on which level the target property is missing the method can be a method that you have defined (SourceMethod) or a method that MapStruct has created (ForgedMethod).

Let us know if we can help you more with finding out the problem. You can also find us on gitter at mapstruct-users

Member

filiphr commented Apr 18, 2017

@mgohin unfortunately there won't be any debug information in the console. Hint for us: Maybe add some more verbose info to display which method is being mapped.

The best way to find out what is happening is to run the compilation in debug mode. I am not sure what you use as your IDE or your build tool. For me with IntelliJ and Maven I run the compile goal with debug and you can find out. You can either break when the NoSuchElementException occurs or in the NestedTargetPropertyMappingHolder at line 288. When you are there see the method in the NestedTargetPropertyMappingHolder. Depending on which level the target property is missing the method can be a method that you have defined (SourceMethod) or a method that MapStruct has created (ForgedMethod).

Let us know if we can help you more with finding out the problem. You can also find us on gitter at mapstruct-users

@mgohin

This comment has been minimized.

Show comment
Hide comment
@mgohin

mgohin Apr 18, 2017

Sorry I deleted my post not to bother because I found the source of my problem.
My question was to know how to find the problem's source.

I keep note of your tip, never used and looks very useful 👍

mgohin commented Apr 18, 2017

Sorry I deleted my post not to bother because I found the source of my problem.
My question was to know how to find the problem's source.

I keep note of your tip, never used and looks very useful 👍

@filiphr

This comment has been minimized.

Show comment
Hide comment
@filiphr

filiphr Apr 19, 2017

Member

@sjaakd I am having a look at this in order to fix it. I have one question for you why not report the error directly in the TargetReference building, but in the BeanMappingMethod? In TargetReference there is a TODO from you saying:

TODO error handling when full fledged target mapping is in place.

and also:

foundEntryMatch = isValid, errors are handled in the BeanMapping, where the error context is known

What we could do is to report the errors there and we have access to the method at that time, and then if the MappingOptions are invalid (they are when there is at least one SourceReference or TargetReference that is not valid, we will return null.

Member

filiphr commented Apr 19, 2017

@sjaakd I am having a look at this in order to fix it. I have one question for you why not report the error directly in the TargetReference building, but in the BeanMappingMethod? In TargetReference there is a TODO from you saying:

TODO error handling when full fledged target mapping is in place.

and also:

foundEntryMatch = isValid, errors are handled in the BeanMapping, where the error context is known

What we could do is to report the errors there and we have access to the method at that time, and then if the MappingOptions are invalid (they are when there is at least one SourceReference or TargetReference that is not valid, we will return null.

filiphr added a commit to filiphr/mapstruct that referenced this issue Apr 23, 2017

#1153 Do not use invalid TargetReferences when creating nested targe…
…t mappings

* Move the error generation for the invalid TargetReference into the BuilderFromTargetMapping
* TargetReference will strip the first entry name in the following cases only if the first entry name matches the MappingTarget parameter, or for reverse mappings it matches the source parameter name
* Pass the reverse source parameter when initializing a reverse mapping

filiphr added a commit to filiphr/mapstruct that referenced this issue Apr 23, 2017

#1153 Do not use invalid TargetReferences when creating nested targe…
…t mappings

* Move the error generation for the invalid TargetReference into the BuilderFromTargetMapping
* TargetReference will strip the first entry name in the following cases only if the first entry name matches the MappingTarget parameter, or for reverse mappings it matches the source parameter name
* Pass the reverse source parameter when initializing a reverse mapping

filiphr added a commit to filiphr/mapstruct that referenced this issue Apr 23, 2017

#1153 Do not use invalid TargetReferences when creating nested targe…
…t mappings

* Move the error generation for the invalid TargetReference into the BuilderFromTargetMapping
* TargetReference will strip the first entry name in the following cases only if the first entry name matches the MappingTarget parameter, or for reverse mappings it matches the source parameter name
* Pass the reverse source parameter when initializing a reverse mapping

@filiphr filiphr closed this in #1184 May 6, 2017

filiphr added a commit that referenced this issue May 6, 2017

#1153 Do not use invalid TargetReferences when creating nested targe…
…t mappings

* Move the error generation for the invalid TargetReference into the BuilderFromTargetMapping
* TargetReference will strip the first entry name in the following cases only if the first entry name matches the MappingTarget parameter, or for reverse mappings it matches the source parameter name
* Pass the reverse source parameter when initializing a reverse mapping
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment