Skip to content

Instantly share code, notes, and snippets.

@dwelch2344
Last active August 29, 2015 13:57
Show Gist options
  • Save dwelch2344/9534833 to your computer and use it in GitHub Desktop.
Save dwelch2344/9534833 to your computer and use it in GitHub Desktop.
HATEOAS doesn't search base classes annotations. See 1_note.md

Notice AbstractResourceController has the actual lookup methods (all of which work). But when an AbstractAssembler implementation builds the links, we don't get the Controller's base URL appended (compare theoutput.json's self vs address ref)

@RestController
public abstract class AbstractResourceController<T> {
public static final int PAGE_SIZE = 20;
@Inject
private AbstractResourceService<T> service;
@Inject AbstractAssembler<T> assembler;
@InitBinder
public void initBinder(WebDataBinder binder) {
// binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd k:m:s"),true));
}
@RequestMapping(value="", method=RequestMethod.GET)
public ResponseEntity<List<Resource<T>>> getAll(@RequestParam(defaultValue = "0") int page){
Pageable p = new PageRequest(page, PAGE_SIZE);
Page<T> result = service.getAll(p);
List<Resource<T>> data = assembler.toResources(result.getContent());
ResponseEntity<List<Resource<T>>> response = new ResponseEntity<List<Resource<T>>>(data, HttpStatus.OK);
return response;
}
@RequestMapping(value="/{id}", method=RequestMethod.GET)
public T getOne(@PathVariable Long id){
return service.getOne(id);
}
@RequestMapping(value="", method=RequestMethod.POST)
public T postOne(@RequestBody T one){
return service.save(one);
}
@RequestMapping(value="/{id}", method=RequestMethod.PUT)
public T putOne(@PathVariable Long id, @RequestBody T payload){
Assert.notNull(payload, "Payload must be provided");
return service.update(id, payload);
}
}
@RestController
@ExposesResourceFor(Address.class)
@RequestMapping("/address")
public class AddressResourceController extends AbstractResourceController<Address>{
@Component
public static class AddressAssembler extends AbstractAssembler<Address> {
@Override
public void addLinks(Collection<Link> links, Address client) {
// methodOn(ClientResourceController.class).getOne(client.getid),
links.add( linkTo( methodOn(ClientResourceController.class).getOne(client.getId()) ).withSelfRel() );
// links.add(linkTo(methodOn(UserController.class).loadUserCustomers(userId)).withRel(customersRel));
// links.add(linkTo(methodOn(UserProfilePhotoController.class).loadUserProfilePhoto(user.getId())).withRel(photoRel));
}
}
// FIXME: if we don't override this, the link is created as "http://localhost:8080/1" instead of "http://localhost:8080/address/1"
@Override
public Address getOne(@PathVariable Long id) {
return super.getOne(id); //To change body of overridden methods use File | Settings | File Templates.
}
}
@RestController
@ExposesResourceFor(Client.class)
@RequestMapping("/clients")
public class ClientResourceController extends AbstractResourceController<Client>{
private static final String REL_ADDRESS = "address";
@Component
public static class ClientAssembler extends AbstractAssembler<Client>{
@Override
public void addLinks(Collection <Link> links, Client client) {
links.add( linkTo( methodOn(ClientResourceController.class).getOne(client.getId()) ).withSelfRel() );
if( client.getAddress() != null ){
links.add( linkTo( methodOn(AddressResourceController.class).getOne(client.getAddress().getId()) ).withRel(REL_ADDRESS) );
}
}
}
}
[
{
"id": 1,
"firstName": "Dave",
"lastName": "Welch",
"email": "[email protected]",
"homePhone": "5555555555",
"mobilePhone": "5555555555",
"secondaryPhone": "5555555555",
"source": "",
"links": [
{
"rel": "self",
"href": "http://localhost:8080/1"
},
{
"rel": "address",
"href": "http://localhost:8080/address/1"
}
]
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment