Subresources in spring REST

I am trying to create a messenger application.

I have to call CommentResource from MessageResource.

I want separate MessageResources and CommentResources.

I am doing something like this:

MessageResource.java

@RestController @RequestMapping("/messages") public class MessageResource { MessageService messageService = new MessageService(); @RequestMapping(value = "/{messageId}/comments") public CommentResource getCommentResource() { return new CommentResource(); } } 

CommentResource.java

 @RestController @RequestMapping("/") public class CommentResource { private CommentService commentService = new CommentService(); @RequestMapping(method = RequestMethod.GET, value="/abc") public String test2() { return "this is test comment"; } } 

I want to

HTTP: // local: 8080 / posts / 1 / comments / a

return "this is a test comment."

Any idea ??

PS: in a word, I want to know the implementation of the JAX-RS sub-resource equivalent in spring-rest

+12
source share
4 answers

Your URL ( http: // localhost: 8080 / messages / 1 / comments / abc ) assumes that comments are attached to the message. Your controller should look like this:

 @RestController @RequestMapping("/messages") public class MessageResource { @RequestMapping(value = "/{messageId}") public String getCommentResource(@PathVariable("messageId") String messageId) { //test return messageId; } @RequestMapping(value = "/{messageId}/comments/{commentsContent}") public String getCommentResource( @PathVariable("messageId") String messageId, @PathVariable("commentsContent") String commentsContent) { //test return messageId + "/" + commentsContent; } } 

I'm not quite sure what you want to do in your MessageResource class, but there is an idea.

Rest - HTTP Methods

This is currently using Get queries. However, you should consider using the appropriate Http method:

  • Get: read resource
  • Post: create a resource
  • Deliver: update
  • Delete: delete :)

Take a look at this: http://www.restapitutorial.com/lessons/httpmethods.html

Example with a message:

 @RequestMapping(method=RequestMethod.POST, value = "/{messageId}/comments/{commentsContent}") public ResponseEntity<String> getCommentResource( @PathVariable("messageId") String messageId, @RequestBody Comment comment) { //fetch the message associated with messageId //add the comment to the message //return success return new ResponseEntity<String>(HttpStatus.OK); } 

Class names

In addition, I would personally rename these classes to MessageController and CommentController.

Edit after comments - Split controllers

You can literally separate the controllers (closer to what you had):

 @RestController @RequestMapping("/messages") public class MessageResource { @RequestMapping(value = "/{messageId}") public String getCommentResource(@PathVariable("messageId") String messageId) { //test return messageId; } } @RestController @RequestMapping("/messages") public class CommentResource { @RequestMapping(value = "/{messageId}/comments/{commentsContent}") public String getCommentResource( @PathVariable("messageId") String messageId, @PathVariable("commentsContent") String commentsContent) { //test return messageId + "/" + commentsContent; } } 
+7
source

What you are looking for is supported in JAX-RS implementations such as Jersey called Sub-Resources . When creating large APIs that become nested in nature, supporting resources are an extremely useful feature.

Spring The default boot implementation of a boot is not JAX-RS , but SpringMVC . Although you can use Jersey in Spring Boot, this has a bit to do with trying to set it up and is apparently not being used or used in the community.

On a side note, DropWizard is awesome!

+3
source

I also forced a switch from JAX-RS to Spring-MVC.

I'm still looking for an elegant way to do this the same as with JAX-RS.

I share what I tried.

 @RestController @RequestMapping("parents") public class ParentsController { @RequestMapping(method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE}) public ResponseEntity<List<Parent>> read() { } @RequestMapping(method = RequestMethod.GET, path = "/{id:\\d+}", produces = {MediaType.APPLICATION_JSON_VALUE}) public ResponseEntity<Parent> read(@PathVariable("id") final long id) { } } 

And ChildrenController .

 @RestController @RequestMapping("/parents/{parentId:\\d+}/children") public class ChildrenController { @RequestMapping(method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE}) @ResponseBody public List<Child> read(@PathVariable("parentId") final long parentId) { } @RequestMapping(method = RequestMethod.GET, path = "/{id:\\d+}", produces = {MediaType.APPLICATION_JSON_VALUE}) @ResponseBody public Child read(@PathVariable("parentId") final long parentId, @PathVariable("id") final long id) { } } 

Two problems that I found

@PathVariable not applicable to fields.

I just can't do @PathVariable("parentId") private long parentId;

No free will for multiple display for ChildrenController

The beauty of JAX-RS is that we can display the ChildrenController for different paths, for example, even ChildrenController has the @Path class with it.

 @Path("/children"); public class ChildrenResource { } @Path("/parents") public class ParentsResource { @Path("/{id}/children") public ChildrenResource resourceChildren() { } } /children /parents/{id}/children 
+1
source

Just create two classes and use a constant to refer to a child resource with a parent resource. This helps establish the relationship between the two classes and make the developer understand the relationship between them.

So:

 @RequestMapping(value= MessageController.URL) public class MessageController { public static final String URL= "/messages"; } 

And:

 @RequestMapping(value = MessageController.URL + "/{idMessage}/comments") public class CommentController { } 

You can also separate the controllers into different packages, showing this hierarchy in your package organization:

 com.company.web.message.MessageController com.company.web.message.comment.CommentController 
+1
source

Source: https://habr.com/ru/post/1259005/


All Articles