So I have been learning REST API with Spring Boot
I have a User bean
@JsonFilter("UserFilter")public class User { private int id; @Size(min = 2, message = "Name should have at least 2 characters") private String name; @JsonProperty("Birth Date") @Past(message = "Birth date should be in the past") private LocalDate birthDate; public User(int id, String name, LocalDate birthDate) { this.id = id; this.name = name; this.birthDate = birthDate; } @Override public String toString() { return "User{" +"id=" + id +", name='" + name +'\''+", birth=" + birthDate +'}'; }}
and I have a UserDao to access User data
@Componentpublic class UserDaoService { private static List<User> users = new ArrayList<>(); static { users.add(new User(1, "Alice", LocalDate.now() .minusYears(18) .minusMonths(1))); users.add(new User(2, "Bob", LocalDate.now() .minusYears(21) .plusMonths(3) .plusDays(5))); users.add(new User(3, "Cathy", LocalDate.now() .minusDays(7) .minusYears(25))); users.add(new User(4, "David", LocalDate.now() .minusYears(23))); } public List<User> findAll() { return users; } public User findById(int id) { return users.stream() .filter(user -> user.getId() == id) .findFirst() .orElse(null); }}
I also have a UserController where I map Endpoints/Requests to REST API responses.
@RestControllerpublic class UserController { private UserDaoService service; public UserController(UserDaoService service) { this.service = service; } @GetMapping("/users") public MappingJacksonValue findAllUsers() { List<User> usersList = service.findAll(); MappingJacksonValue mjv = new MappingJacksonValue(usersList); SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter.filterOutAllExcept("name", "Birth Date"); FilterProvider filters = new SimpleFilterProvider().addFilter("UserFilter", filter); mjv.setFilters(filters); return mjv; } @GetMapping("/users/{id}") public EntityModel<User> findUserById(@PathVariable int id) { User usr = service.findById(id); if (usr == null) throw new UserNotFoundException("id:" + id); EntityModel<User> model = EntityModel.of(usr); WebMvcLinkBuilder link = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(this.getClass()).findAllUsers()); model.add(link.withRel("all-users")); return model; }}
For the findAllUsers() method I tried to make use of dynamic filtering using MappingJacksonValue. For findUserById() method I don't want to apply any filtering but I do want to add a link to the full list of users (using EntityModel) when a person views details on a single user.
When I make a GET request to localhost:8080/users/3 I get the following error:HttpMessageConversionException: type definition error: [simple type, class SpringBootFramwork.RESTAPI.beans.User]
caused by InvalidDefinitionException: Cannot resolve PropertyFilter with id 'UserFilter'; no FilterProvider configured (through reference chain: org.springframework.hateoas.EntityModel["content"])
It seems when I comment out the @JsonFilter annotation from the User bean the GET request works, but of course no filtering when I GET localhost:8080/users (retrieve all of the users). Why is it when I add the @JsonFilter annotation to my User bean I get the above error? How can I fix this?
Expected Response:{"id": 3,"name": "Cathy","Birth Date": "1999-04-19","_links": {"all-users": {"href": "http://localhost:8080/users"}}}