Thanks to visit codestin.com
Credit goes to GitHub.com

Skip to content

Conversation

@AlexElin
Copy link

@AlexElin AlexElin commented Oct 3, 2024

At the moment when a mapper depends on another mappers which are passed via constructor, the call Mappers.getMapper(...) fails with an exception "java.lang.NoSuchMethodException: MapperName.()"

This pull request fixes the issue by resolving such dependencies

@filiphr
Copy link
Member

filiphr commented Oct 20, 2024

This is a bit tricky @AlexElin. What if one of the parameters for the constructor is not a mapper? What if there is a cyclic dependency?

I would rather leave the Mappers factory simple as is and if you want something more complex you can always use your own custom component model

@RafaelRfs
Copy link

I'm passing by it, there's a bug on Intellij in Java 11, when i put

@Mapper(componentModel = "spring", uses = {
        TechnologiesMapper.class
},injectionStrategy = InjectionStrategy.CONSTRUCTOR)
public interface ProjectsMapper {

    Project mapToProject(ProjectsDomain projectsDomain);

}

In the unit tests

package com.site.rfs.blog.dataproviders.mappers;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mapstruct.factory.Mappers;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import static org.junit.jupiter.api.Assertions.*;
@ExtendWith(SpringExtension.class)
class ProjectsMapperTest {

    private ProjectsMapper projectsMapper;

    @BeforeEach
    public void setUp(){
        this.projectsMapper = Mappers.getMapper(ProjectsMapper.class);
    }

    @Test
    public void test(){
        assertNotNull(this.projectsMapper);
    }

}

It throws a error:

java.lang.RuntimeException: java.lang.NoSuchMethodException:

Debugging the code it' happen when calling the line 49 of the method doGetMapper:

Constructor constructor = implementation.getDeclaredConstructor() at the

When i change the injection strategy, it's change the behavior and i'ts work:

InjectionStrategy.SETTER
or
InjectionStrategy.FIELD(default);

Please accept the fix of AlexELin, it'll help everyone

@filiphr
Copy link
Member

filiphr commented Dec 1, 2024

@RafaelRfs that's not a bug in IntelliJ, it's rather a wrong usage of the Mappers#getMapper factory.

As I wrote in my earlier comment, I am not a fan of making Mappers#getMapper more complex and do dependency injection. The Mappers factory always looks for a class named <MapperName>Impl. However, the constructor parameters do not need to be mappers, they can be other classes.

You can always just use new ProjectsMapperImpl(...) in your tests.

@janmaterne
Copy link

When using Spring, why calling the factory and not letting Spring inject the mapper?


@ExtendWith(SpringExtension.class)
class ProjectsMapperTest {

    @Autowired
    private ProjectsMapper projectsMapper;

    // no call to Mappers.getMapper()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants