Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring REST response is different in a custom controller

I have several controllers that are automatically creating REST endpoints.

@RepositoryRestResource(collectionResourceRel = "books", path = "books")
public interface BooksRepository extends CrudRepository<Books, Integer> {
    public Page<Books> findTopByNameOrderByFilenameDesc(String name);
}

When I visit: http://localhost:8080/Books

I get back:

{
    "_embedded": {
        "Books": [{
            "id": ,
            "filename": "Test123",
            "name": "test123",
            "_links": {
                "self": {
                    "href": "http://localhost:8080/books/123"
                },
                "Books": {
                    "href": "http://localhost:8080/books/123"
                }
            }
        }]
    },
    "_links": {
        "self": {
            "href": "http://localhost:8080/books"
        },
        "profile": {
            "href": "http://localhost:8080/profile/books"
        },
        "search": {
            "href": "http://localhost:8080/books/search"
        },
        "page": {
            "size": 20,
            "totalElements": 81,
            "totalPages": 5,
            "number": 0
        }
    }
}

When I create my own controller:

@Controller
@RequestMapping(value = "/CustomBooks")
public class CustomBooksController {
    @Autowired
    public CustomBookService customBookService;

    @RequestMapping("/search")
    @ResponseBody
    public Page<Book> search(@RequestParam(value = "q", required = false) String query,
                                 @PageableDefault(page = 0, size = 20) Pageable pageable) {
        return customBookService.findAll();
    }
}

I'll get a response back that looks nothing like the automatically generated controller response:

{
    "content": [{
        "filename": "Test123",
        "name" : "test123"
    }],
    "totalPages": 5,
    "totalElements": 81,
    "size": 20,
    "number": 0,
}

What do I need to do to make my response look like the automatically generated response? I want to keep it consistent, so I don't have to rewrite code for a different response. Should I be doing it a different way?


Edit: Found this: Enable HAL serialization in Spring Boot for custom controller method

But I don't understand what I need to change in my REST Controller to enable: PersistentEntityResourceAssembler. I've searched on Google for PersistentEntityResourceAssembler, but it keeps leading me back to similar pages without much of an example (or the example doesn't seem to work for me).

like image 376
Kevin Vasko Avatar asked Dec 01 '16 23:12

Kevin Vasko


1 Answers

As @chrylis suggested you should replace your @Controller annotation with @RepositoryRestController for spring-data-rest to invoke it's ResourceProcessors for customizing the given resource.

For you resource to follow the HATEOAS specification (like your spring-data-rest BooksRepository) your method declaration return type should be like HttpEntity<PagedResources<Resource<Books>>> For converting your Page object to PagedResources:

  • You need to autowire this object.

    @Autowired private PagedResourcesAssembler<Books> bookAssembler;

  • Your return statement should be like

    return new ResponseEntity<>(bookAssembler.toResource(customBookService.findAll()), HttpStatus.OK);

These changes should help you to get a org.springframework.hateoas.Resources compliant response containing the "_embedded" and "_links" attribute.

like image 57
Alex Ciocan Avatar answered Nov 05 '22 19:11

Alex Ciocan