javaspringmapstructhttpbackend

Parameter x of constructor in ... required a bean of type '...' that could not be found


I am working on a personal project with Spring Boot. I am getting the following error:

Parameter 2 of constructor in com.learningapp.backend.AcademixHub.services.UserService required a bean of type 'com.learningapp.backend.AcademixHub.mappers.UserMapper' that could not be found.

Here is the code of UserService.java:

@Service
public class UserService {
     private final UserRepository userRepository; 

        private final  PasswordEncoder passwordEncoder;

        private final UserMapper userMapper;    
        
        
    
    public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder, UserMapper userMapper) {
            super();
            this.userRepository = userRepository;
            this.passwordEncoder = passwordEncoder;
            this.userMapper = userMapper;
        }


     public UserDto register(SignUpDto signupDto) {
         System.out.println("hello man hi hello");
            Optional<User> optionalUser = userRepository.findByEmail(signupDto.getEmail());

            if (optionalUser.isPresent()) {
                throw new AppException("Login already exists", HttpStatus.BAD_REQUEST);
            }

            User user = userMapper.signUpToUser(signupDto);
            user.setPassword(passwordEncoder.encode(signupDto.getPassword()));

            User savedUser = userRepository.save(user);

            return userMapper.toUserDto(savedUser);
        }
     
     public UserDto login(LoginDto loginDto) {
            User user = userRepository.findByEmail(loginDto.getEmail())
                    .orElseThrow(() -> new AppException("Unknown user", HttpStatus.NOT_FOUND));

            if (passwordEncoder.matches(loginDto.getPassword(), user.getPassword())) {
                return userMapper.toUserDto(user);
            }
            throw new AppException("Invalid password", HttpStatus.BAD_REQUEST);
        }


        public UserDto findByEmail(String login) {
            User user = userRepository.findByEmail(login)
                    .orElseThrow(() -> new AppException("Unknown user", HttpStatus.NOT_FOUND));
            return userMapper.toUserDto(user);
        }

}

Here is the code of UserMapper.java:

@Mapper(componentModel="spring")
@Component
public interface UserMapper {
    
    UserDto toUserDto(User user);
    
    @Mapping(target = "password", ignore = true)
    User signUpToUser(SignUpDto signUpDto);
    
}

If I remove final from those three variables and add a default constructor, the server runs properly. However, if I hit the register endpoint with a POST request, I get another error:

[Request processing failed: java.lang.NullPointerException: Cannot invoke "com.learningapp.backend.AcademixHub.repository.UserRepository.findByEmail(String)" because "this.userRepository" is null] with root cause

What Should I do to fix this?


Solution

  • Spring complains that no bean implementing UserMapper where found. The most probable cause is that UserMapperImpl has not been generated by MapStruct annotation processor. It should be located in the same package than UserMapper, but under target/generated-sources.

    Do you find it after maven compilation (running mvn compile)?

    maven, gradle

    For this implementation to be generated during compilation with maven, the annotation processing must be configured in maven pom.xml:

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven-compiler-plugin.version}</version>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${mapstruct.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>
    

    See https://mapstruct.org/documentation/installation where you'll find this information for gradle too.

    IDE support

    Mappers can also be generated during development with your IDE. See https://mapstruct.org/documentation/ide-support/


    You can also have a look at https://www.baeldung.com/mapstruct to understand how MapStruct works.

    @Component is not needed on UserMapper as it will be automatically added on the UserMapperImpl implementation.

    You are using constructor injection, which is fine, do not add a default constructor because dependencies won't be injected (all fields will remain null, causing the NullPointerException you described).