0

I need to use Mapstruct and this error is comming up.

*APPLICATION FAILED TO START Description: Field userMapper in com.mycomp.myappapi.service.UserService required a bean of type 'com.mycomp.myappapi.mapper.UserMapper' that could not be found. The injection point has the following annotations:

  • @org.springframework.beans.factory.annotation.Autowired(required=true) Action: Consider defining a bean of type 'com.mycomp.myappapi.mapper.UserMapper' in your configuration.*

Since there's this line in myappapiApplication.java, understand it should be able to find UserMapper.java. But for some reason it's not.

@ComponentScan(basePackages = {"com.mycomp.*"})

Also, it is not autogenerating the mapstruct implementation classes in \target folder.

package com.mycomp.myappapi;


@SpringBootApplication
@EntityScan(basePackages = {"com.mycomp.myappapi.model"})
@ComponentScan(basePackages = {"com.mycomp.*"})
@EnableJpaRepositories(basePackages = {"com.mycomp.myappapi.repository"})
@EnableTransactionManagement
@EnableWebMvc
@RestController
@EnableAutoConfiguration
public class myappapiApplication {

    public static void main(String[] args) {
        SpringApplication.run(myappapiApplication.class, args);
    }

}
package com.mycomp.myappapi.mapper;


@Mapper(componentModel = "Spring")
public interface UserMapper {   
    
    User UserRequestDTOtoUser(UserRequestDTO userRequestDTO);
    
    UserResponseDTO UserToUserResponseDTO(User user);
    
    
}
package com.mycomp.myappapi.service;

...

@Service
@Transactional
public class UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private UserRepository userRepository;      
    
    public UserResponseDTO saveUser(UserRequestDTO userRequestDTO) {
        
        User user = userMapper.UserRequestDTOtoUser(userRequestDTO);
        
        ...
        
        User savedUser = userRepository.save(user);
        
        UserResponseDTO userResponseDTO = userMapper.UserToUserResponseDTO(savedUser);      
        
        return userResponseDTO;
    }
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.7</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.mycomp.myappapi</groupId>
    <artifactId>myappapi</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>myappapi</name>
    <description>aaa</description>
    <properties>
        <java.version>11</java.version>
        <org.mapstruct.version>1.5.2.Final</org.mapstruct.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jdbc</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>
                
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
    
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>
        
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <!--<version>3.8.1</version>-->
                <version>${maven-compiler-plugin.version}</version>
                <configuration>
                    <source>11</source> <!-- depending on your project -->
                    <target>11</target> <!-- depending on your project -->
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>                        
                        <!-- other annotation processors -->
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
            
        </plugins>
        
    </build>

</project>
jkfe
  • 549
  • 7
  • 29

2 Answers2

0

Try using spring instead of Spring. The documentation does not have an upper case. Even better: add the config to your pom.xml, then you don't have to specify the componentModelfor every mapper:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <!--<version>3.8.1</version>-->
    <version>${maven-compiler-plugin.version}</version>
    <configuration>
        <source>11</source> <!-- depending on your project -->
        <target>11</target> <!-- depending on your project -->
        <annotationProcessorPaths>
            <path>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct-processor</artifactId>
                <version>${org.mapstruct.version}</version>
            </path>
            <!-- other annotation processors -->
        </annotationProcessorPaths>
        <compilerArgs>
            <compilerArg>-Amapstruct.defaultComponentModel=spring</compilerArg>
        </compilerArgs>
    </configuration>
</plugin>
times29
  • 2,782
  • 2
  • 21
  • 40
  • I tried both ways and neither of them worked. I don't think that is the problem as I have used uppercase @Mapper(componentModel = "Spring") in the past with no issues. – jkfe Jan 30 '23 at 21:23
0

according to this guide: https://www.baeldung.com/mapstruct#2-inject-spring-components-into-the-mapper

Sometimes, we'll need to utilize other Spring components inside our mapping logic. In this case, we have to use an abstract class instead of an interface

try to change UserMapper into an abstract class.

Sharon Ben Asher
  • 13,849
  • 5
  • 33
  • 47
  • I've tried that already. Then the error changes to this one: java.lang.ClassNotFoundException: Cannot find implementation for com.mycomp.myappapi.mapper.UserMapper - and the MapStruct autogenerated classes are still not created in the \target folder. – jkfe Jan 30 '23 at 21:35
  • according to this answer https://stackoverflow.com/questions/61710510/mapstruct-cannot-find-implementation you should do `mvn clean install` – Sharon Ben Asher Jan 30 '23 at 21:47
  • are you running the application in IDE? if so, you need to enable annotation processing in the IDE – Sharon Ben Asher Jan 30 '23 at 21:51
  • maven clean install is the same as going to STS > right click project name in Package Explorer > Run As > maven clean, rigth? When I do that and run it again I get this error: "Error: Could not find or load main class com.mycomp.myappapi.myappapiApplication Caused by: java.lang.ClassNotFoundException: com.mycomp.myappapi.myappapiApplication" Then I go to STS > Project > Clean, run it again and it goes back to the same error of the original question. – jkfe Jan 30 '23 at 21:53
  • yes, I'm running it in Spring Tool Suite IDE. Already had annotation processing configured by going to Project > Properties > Java Compiler > Annotation Processing > checked "Enable project Specific Settings", checked "Enable annotation processing", checked "Enable processing in editor" – jkfe Jan 30 '23 at 21:57