Kevin Vasko
Kevin Vasko

Reputation: 1655

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).

Upvotes: 5

Views: 2358

Answers (1)

Alex Ciocan
Alex Ciocan

Reputation: 2322

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.

Upvotes: 6

Related Questions