gg ff
gg ff

Reputation: 519

Cant understand why RepositoryRestController does not work?

I use Spring Data Rest and I can not understand why my RepositoryRestController does not work. Its code:

  @RepositoryRestController
  public class Cntrl {
  @Autowired
  private UserDao userDao;


  @RequestMapping(name = "/users/{id}/nameOne",method = 
  RequestMethod.GET)
  @ResponseBody
  public PersistentEntityResource setNameOne(@PathVariable("id") Long id, PersistentEntityResourceAssembler persistentEntityResourceAssembler){
User user = userDao.findById(id).orElseThrow(()->{
throw new ServerException("Wrong id");
});

user.setLogin("One");
userDao.save(user);
return persistentEntityResourceAssembler.toFullResource(user);
 }
 }

And Spring Boot start class:

    @SpringBootApplication
    @EnableWebMvc
    @EnableScheduling
    @EnableJpaRepositories
    @EnableSpringDataWebSupport
    public class Application {
    public static void main(String[] args) throws Exception {
    SpringApplication.run(Application.class, args);
    }
    }

When i go to base path (localhost:8080/api) everything is fine, but when send GET to request to localhost:8080/api/users/1/nameOne I get empty response, i dont have other controllers and I have user with id 1, so why it is not working ?

Upvotes: 1

Views: 1252

Answers (3)

Florian Bachmann
Florian Bachmann

Reputation: 572

As far as I could figure out, if you use a RepositoryRestController you must activate the path using a corresponding RestRepositoryResource, before it's available in a controller, i.e. this would work:

// new code
@RepositoryRestResource(path = "/users")
public interface UserDaoRepository extends Repository<UserDao, String> {}

// your code
@RepositoryRestController
public class Cntrl {
  @Autowired
  private UserDao userDao;


  @RequestMapping(name = "/users/{id}/nameOne",method = 
  RequestMethod.GET)
  @ResponseBody
  public PersistentEntityResource setNameOne(@PathVariable("id") Long id, PersistentEntityResourceAssembler persistentEntityResourceAssembler){
      User user = userDao.findById(id).orElseThrow(()->{
      throw new ServerException("Wrong id");
    });

    user.setLogin("One");
    userDao.save(user);
    return persistentEntityResourceAssembler.toFullResource(user);
  }
}

Alternatively, you could opt to use a BasePathAwareController instead of RepositoryRestController, which does not require a resource.

@BasePathAwareController  // <<<< NOT @RepositoryRestController
public class Cntrl {
  @Autowired
  private UserDao userDao;

  @RequestMapping(name = "/users/{id}/nameOne",method = RequestMethod.GET)
  @ResponseBody
  public PersistentEntityResource setNameOne(@PathVariable("id") Long id, PersistentEntityResourceAssembler persistentEntityResourceAssembler){
      User user = userDao.findById(id).orElseThrow(()->{
      throw new ServerException("Wrong id");
    });

    user.setLogin("One");
    userDao.save(user);
    return persistentEntityResourceAssembler.toFullResource(user);
  }
}

Upvotes: 0

mahsum
mahsum

Reputation: 350

It doesn't work because the URL structure you are using has already a meaning in Spring Data Rest context.

/{repository}/{id}/{column} URL is handled at RepositoryPropertyReferenceController.followPropertyReference method.

/api/users/1/nameOne means: get the nameOne column of the user with the id of 1. An important note is that: this column should reference another @Entity. This means if you have a String column named "surname" and you hit the URL /api/users/1/name you will get 404 because this column is not referencing another entity. If you have a column named school which references to a School entity and you hit the URL /api/users/1/school you will get the referenced school entity for that user. If the user does not have a school then you will get 404 again.

Also, @RepositoryRestController can be used for @RequestMapping if the URL you are giving isn't colliding with Spring Data Rest.

You can test that with the following example:

@RepositoryRestController
public class CustomRepositoryRestController {
    @RequestMapping(path = "/repositoryRestControllerTest", method = RequestMethod.GET)
    @ResponseBody
    public String nameOne() {
        return "test";
    }

}

Visit http://localhost:8080/repositoryRestControllerTest

I hope this explanation clarifies things for you.

Upvotes: 3

Maciej Kowalski
Maciej Kowalski

Reputation: 26542

If localhost:8080/api is your root context, then localhost:8080/api/users/1/nameOne should be the url you are using for the user GET.

Upvotes: 0

Related Questions