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:
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;
}
}
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);
}
}
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.