Search code examples
javaspringjavabeans

Consider defining a bean of type 'UserConverter' in your configuration


I don't know what happend with my spring boot application but now I can't to start it because of an error:

***************************
APPLICATION FAILED TO START
***************************
Description:
Field userConverter in webapp.controllers.UserResourceController required a bean of type 'webapp.converter.UserConverter' 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 'webapp.converter.UserConverter' in your configuration.
Process finished with exit code 1

Controller code:

@RestController
@RequestMapping("/api/user")
public class UserResourceController {

@Autowired
private UserServiceImpl userService;

@Autowired
private UserConverter userConverter;

@PostMapping
public ResponseEntity<UserDto> addUser(@RequestBody UserDto userDto) {
    userService.persist(userConverter.toUser(userDto));
    return ResponseEntity.ok().body(userDto);
}

@GetMapping
public ResponseEntity<List<UserDto>> findAllUsers() {
    return ResponseEntity.ok(userConverter.toUserDtos(userService.getAll()));
}

@PutMapping("/api/user/{id}")
public ResponseEntity<UserDto> updateUser(@PathVariable Long id, @RequestBody UserDto userDto) {
    User user = userConverter.toUser(userDto);
    user.setId(id);
    userService.persist(user);
    return ResponseEntity.ok().body(userDto);
}

@GetMapping("/api/user/{id}")
public ResponseEntity<UserDto> findUser (@PathVariable Long id) {
    Optional<User> user = Optional.ofNullable(userService.getByKey(id));
    return ResponseEntity.ok(userConverter.toUserDto(user.get()));
}
}

The mapper class:

@Mapper(componentModel = "spring")
@Service
public abstract class UserConverter {
    public abstract User toUser(UserDto userDto);
    public abstract UserDto toUserDto(User user);
    public abstract List<UserDto> toUserDtos(List<User> users);
}

The first I tried to run it without @Service annotation, and then with it annotation but I always see the same error.


Solution

  • You couldn't inject an abstract class which doesn't have any real implementation. It isn't possible in Java even without Spring. So have do you expect it could be injected?

    I don't understand why do you need to inject that class. The best solution will create a utility class with the appropriate converter, like:

    public final class UserConverter {
        private UserConverter() {}
    
        public static UserDTO toUserDTO(User employee) {
            Department empDp = employee.getDepartment();
            return UserDTO.builder()
                    .id(employee.getId())
                    .name(employee.getName())
                    .active(employee.getActive())
                    .departmentId(empDp.getId())
                    .departmentName(empDp.getName())
                    .build();
        }
    
        public static User toUser(UserDTO dto) {
            Department dp = Department.builder()
                    .id(dto.getDepartmentId())
                    .name(dto.getDepartmentName())
                    .build();
            return User.builder()
                    .id(dto.getId())
                    .name(dto.getName())
                    .active(dto.getActive())
                    .department(dp)
                    .build();
        }
    }
    

    And call it as a static method from your code:

    @GetMapping("/{id}")
    public ResponseEntity<UserDto> findUser (@PathVariable Long id) {
        return userService.getByKey(id)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }
    

    Also, your code has some mistakes for your API:

    • mapping to resource should be plural like @RequestMapping("/api/users") -> and only when you need operation by id add @GetMapping("/{id}")
    • create method should return 201 - Create status code instead of 200
    • if /api should be common for all your API you could define it at the configuration file for all your resources.
      Snippet from applicatoin.yml:

      server: servlet: context-path: /api

    Useful references for solutions with MapStruct: