0

well, this is my first question on Stackoverflow, so I hope, I'm explaining my Problem good enough :-)

I am working with Spring Data Rest MongoDB. I'm using some of the "magic" methods that are available just by implementing MongoRepository, but I'm also using custom implementations and a RestController. So let me show you some code:

My repository looks like this:

public interface BookRepository extends MongoRepository<Book, String>{
   //here are some methods that don't play a role here
}

Now my Frontend is made by good old AngularJS and calls some of the magic Spring Data Rest methods like GET and PUT on the self link of a resource. But now I need some server-side logging after calling PUT. So I decided to make some own implementation for PUT - but not for GET. PUT works fine but unfortunately GET doesn't work anymore. I'm always getting "Request method 'GET' not supported" in my logs.

My RestController looks like this now:

@RepositoryRestController
@RequestMapping("/book/{mongoId}")
public class BookRestController {

    @Autowired
    private ResourceProcessor<Resource<Book>> bookResourceProcessor;

    @Autowired
    private BookRepository bookRepository;

    private static Logger LOG = 
        Logger.getLogger(BookRestController.class);


    @RequestMapping(method = RequestMethod.PUT,
        consumes = MediaType.APPLICATION_JSON_VALUE)
    public
    @ResponseBody
    ResponseEntity<Resource<Book>> updateBookAndLog(
        @RequestBody Book book,
        @PathVariable(value = "mongoId") String mongoId,
        @RequestHeader("MyApp-User") String userId,
        @RequestHeader("MyApp-Action") String action) {

        Book bookBeforeUpdate = bookRepository.findOne(mongoId);
        LOG.info("Log something");

        book.setMongoId(mongoId);
        Book responseBook = bookRepository.save(book);

        return ResponseEntity.ok(bookResourceProcessor.process(new 
           Resource<book>(responseBook)));
    }
}

Here an example of a GET and a PUT from my frontend:

myApp.factory('Book', function($http, $q, ConfigurationHelper) {

    return {
       getById: function (bookId) {
          return $http.get('book/' + bookId);
       },

       save: function(book, userId, action) {
            return $http.put(book._links.self.href, book,
                {headers: {"MyApp-User": userId,
                        "MyApp-Action" : action}
                });
        }
    }

So now my question(s): Is it because PUT and POST are using the same URL (the self link of the book resources) - do I have to either implement all HTTP methods for one URL or none? Is there anthing I have missed?

devdre
  • 33
  • 5

1 Answers1

0

You need a verb per endpoint so you'll need a @RequestMapping(method = RequestMethod.GET) method to handle the GET request.

On a side note, the Spring team recommend constructor injection over @Autowired:

public BookRestController(ResourceProcessor<Resource<Book>> bookResourceProcessor, BookRepository bookRepository) {
  this.bookResourceProcessor = bookResourceProcessor;
  this.bookRepository = bookRepository;
}
codebrane
  • 4,290
  • 2
  • 18
  • 27
  • Thanks for your answer, just want to make sure, we understand each other correctly: Before I implemented the PUT-method from my example, PUT and GET worked because of the RepositoryRestResource-Annotation(I forgot this in my example - I will add it.) I'm just wondering why GET doesn't work now, when I implemented PUT. So what you say means that I do have to implement both verbs as soon as I implement one of them? – devdre May 02 '18 at 13:00
  • no probs, your BookRestController doesn't have a GET handler – codebrane May 02 '18 at 13:35
  • actually, if you don't specify a RequestMapping, the same method can handle all verbs. When you specifically add PUT, it's no longer default, so you need to also specify GET in order to allow GET requests https://stackoverflow.com/questions/38811606/what-is-the-default-request-method-type-for-the-request-mapping – codebrane May 05 '18 at 13:53
  • I know that there is no GET handler. I wanted to override PUT but still have the other HTTP methods like spring data rest exposes them automatically. Maybe the person who has written the following Question explained it better: https://stackoverflow.com/questions/36773171/spring-data-rest-override-repository-method-on-the-controller – devdre May 07 '18 at 15:22