Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mix Spring Data Repositories and Spring Rest Controllers

Currently I am exposing a few Spring Data Repositories as RESTful services by annotating them with @RepositoryRestResource like this:

@RepositoryRestResource(collectionResourceRel = "thing1", path = "thing1")
public interface Thing1Repository extends PagingAndSortingRepository<Thing1, String> {}

@RepositoryRestResource(collectionResourceRel = "thing2", path = "thing2")
public interface Thing2Repository extends CrudRepository<Thing2, String> {}

This all works great. When you hit my first endpoint is also shows all the Spring Data Repositories I have exposed, like this:

{
   _links: {
      thing1: {
         href: "http://localhost:8080/thing1{?page,size,sort}",
         templated: true
      },
      thing2: {
         href: "http://localhost:8080/thing2"
      }
   }
}

Now I have some endpoints I want to expose that cannot be represented by Spring Data Repositories, so I am using a RestController.

Here is a simple example:

@RestController
@ExposesResourceFor(Thing3.class)
@RequestMapping("/thing3")
public class Thing3Controller {

  @Autowired 
  EntityLinks entityLinks;

  @Autowired 
  Thing3DAO thing3DAO;

  //just assume Thing3.class extends ResourceSupport. I know this is wrong, but it makes the example shorter  
  @RequestMapping(value = "/{id}", produces = "application/json")
  Thing3 thing3(@PathVariable("id") String id)
  {
      Thing3 thing3 = thing3DAO.findOne(id);         

      Link link = entityLinks.linkToSingleResource(Thing3.class, id);
      thing3.add(link);

      return thing3;
  }
}

Now if I run this app and go to:

http://localhost:8080/thing3/{id} 

I do get a JSON representation of the Thing3 with a link to itself, that works as expected.

What I want to figure out how to do is have the first endpoint also describe this controller. I basically want this:

{
   _links: {
      thing1: {
         href: "http://localhost:8080/thing1{?page,size,sort}",
         templated: true
      },
      thing2: {
         href: "http://localhost:8080/thing2"
      },
      thing3: {
         href: "http://localhost:8080/thing3"
      }
   }
}

What do I need to do to get my base endpoint to have a link to this controller?

like image 503
dspiegs Avatar asked Dec 09 '14 20:12

dspiegs


People also ask

Is used for exposing spring data repositories over rest using Spring data rest?

Spring Data REST can be used to expose HATEOAS RESTful resources around Spring Data repositories. Without writing a lot of code, we can expose RESTful API around Spring Data Repositories.

What is the difference between spring controller and rest controller?

@Controller is used to mark classes as Spring MVC Controller. @RestController annotation is a special controller used in RESTful Web services, and it's the combination of @Controller and @ResponseBody annotation. It is a specialized version of @Component annotation.

How are spring data repositories actually implemented?

In the repository interfaces, we can add the methods like findByCustomerNameAndPhone() (assuming customerName and phone are fields in the domain object). Then, Spring provides the implementation by implementing the above repository interface methods at runtime (during the application run).

What is difference between JpaRepository and CrudRepository?

Crud Repository is the base interface and it acts as a marker interface. JPA also provides some extra methods related to JPA such as delete records in batch and flushing data directly to a database. It provides only CRUD functions like findOne, saves, etc. JPA repository also extends the PagingAndSorting repository.


1 Answers

You could override RepositoryLinkResource, and add a resource pointing to your thing3:

resource.add(ControllerLinkBuilder.linkTo(Thing3Controller.class).withRel("thing3"));

Check this question: Custom response for root request int the Spring REST HATEOAS with both RepositoryRestResource-s and regular controllers

like image 142
Leandro Carracedo Avatar answered Sep 19 '22 16:09

Leandro Carracedo