Search code examples
javaspring-data-jpaspring-dataspring-hateoas

After overriding RestController method I get: org.springframework.dao.InvalidDataAccessApiUsageException: The given id must not be null


I want to add spring-hateoas to my portfolio project and make it fully restful. That means that I need to override methods given by AbstractResource class(this is base class for my @RestController's) to edit it for my needs and when I do so I get org.springframework.dao.InvalidDataAccessApiUsageException: The given id must not be null!

My project look as follows:

  • service package
public interface AbstractService<ENTITY extends AbstractEntity> {

    ENTITY update(ENTITY entity);

    EntityModel<ENTITY> getById(Long id);

    ENTITY save(ENTITY entity);

    void delete(Long id);

    Collection<ENTITY> getAll();
}

public abstract class AbstractServiceImpl<ENTITY extends AbstractEntity> implements AbstractService<ENTITY> {

    protected abstract JpaRepository<ENTITY, Long> getRepository();

    @Override
    public Collection<ENTITY> getAll() {
        return getRepository().findAll();
    }

    @Override
    public EntityModel<ENTITY> getById(Long id) {
        return EntityModel.of(getRepository().getOne(id));
    }
}

@Service
public class UserServiceImpl extends AbstractServiceImpl<User> implements UserService {

    private final UserRepository userRepository;

    @Override
    protected JpaRepository<User, Long> getRepository() {
        return userRepository;
    }
}
  • resource package
public abstract class AbstractResource<ENTITY extends AbstractEntity>{

    public abstract AbstractService<ENTITY> getService();

    @GetMapping(value = "/{id}", produces = {"application/hal+json"})
    public EntityModel<ENTITY> getById(@PathVariable("id") Long id) {
        return getService().getById(id);
    }

    @GetMapping
    public Collection<ENTITY> getAll() {
        return getService().getAll();
    }
}

When I leave this like so - everything works normal - I get responses as expected

@RestController
@RequestMapping("/api/users")
public class UserResource extends AbstractResource<User> {

    @Autowired
    private final UserService userService;

    @Override
    public AbstractService<User> getService() {
        return userService;
    }
}

Error ocurrs when I try to override this method

@RestController
@RequestMapping("/api/users")
public class UserResource extends AbstractResource<User> {

    @Autowired
    private final UserService userService;

    @Override
    public AbstractService<User> getService() {
        return userService;
    }

    @Override
    public EntityModel<User> getById(Long id) {
        return userService.getById(id);
        or
        return super.getById(id);
    }
}

Solution

  • After UserResource overrides AbstractResource.getById(Long), though the annotation @GetMapping(value = "/{id}", produces = {"application/hal+json"}) is inherited, the annotation @PathVariable("id") is not. Put the annotation @PathVariable("id") within UserResource.getById(Long) should solve your problem.

    It's highly recommended to put a runnable sample project (including request URL and test data) in Github to reproduce the error you encountered. Otherwise, it's difficult to find out the cause and verify.