title: How and where validate ownership of resource in spring boot rest delete endpoint
body: <p>I am writing simple spring boot rest application and i come up with little architecture problem while creating DELETE endpoint. I have try way to solve this problem and I need advice which one is better and why.</p>
  
  <p>First of all, I have class annoted with <code>@ControllerAdvice</code> which contains exception handlers:</p>
  
  <pre><code>@ExceptionHandler(ResourceNotFoundException.class)
  public ResponseEntity&lt;String&gt; handleResourceNotFoundException(ResourceNotFoundException ex) {
      return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
  }
  
  @ExceptionHandler(ResourceNotAccessException.class)
  public ResponseEntity&lt;String&gt; handleResourceNotAccessException(ResourceNotAccessException ex) {
      return ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED).body(ex.getMessage());
  }
  </code></pre>
  
  <p>So i want to create endpoint :</p>
  
  <pre><code>@DeleteMapping("/{offerId}")
  public void deleteOffer(@PathVariable Long offerId, Authentication authentication) {
  // here code to delete offer.
  }
  </code></pre>
  
  <p>So the main assumption is that logged user can delete offer which id is equals to offeId and he is owner of that offer (ownership i can check using code : <code>offer.getOwner().getUsername().equals(authentication.getName());</code> ) or has Role.ADMIN</p>
  
  <p>I figure out three ways to do this:</p>
  
  <h2><strong>First</strong></h2>
  
  <p>All logic in controller and only simple method</p>
  
  <pre><code>@DeleteMapping("/{offerId}")
  public void deleteOffer(@PathVariable Long offerId, Authentication authentication) {
      AbstractOffer offer = offerService.findOfferById(offerId).orElseThrow(() -&gt; new ResourceNotFoundException("Offer with given Id doesn't exists."));
      if (!offerService.isOwner(offer,authentication)) throw new ResourceNotAccessException("Cannot delete offer if you aren't owner");
      offerService.deleteOffer(offer);
  }
  </code></pre>
  
  <h2>Second</h2>
  
  <p>Logic to remove this resource put into either <code>PermissionEvaluator</code> or validate using SPeL and annotation <code>@PreAuthorize(...)</code> In this case i am not throwing any exception and there is not called ControllerAdvice</p>
  
  <p>`</p>
  
  <h2>Third</h2>
  
  <p>Put all logic into service class and from controller only call this method.</p>
  
  <pre><code>@Service
  public class OfferService {
  .
  .
  .
  public void deleteOfferIfOwner(Long offerId,Authentication authentication) {
      AbstractOffer offer = findOfferById(offerId).orElseThrow(() -&gt; new ResourceNotFoundException("Offer with given Id doesn't exists."));
      if(!isOwner(offer,authentication)) throw new ResourceNotAccessException("Cannot delete offer if you aren't owner");
      deleteOffer(offer);
  }
  .
  .
  }
  </code></pre>
  
  <p>Then:</p>
  
  <pre><code>@DeleteMapping("/{offerId}")
  public void deleteOffer(@PathVariable Long offerId, Authentication authentication) {
      offerService.deleteOfferIfOwner(offerId,authentication);
  }
  </code></pre>
  
  <h2>Summary</h2>
  
  <p>In my opinion first solution is good because exception are connected to controller and are translated to response but i am not sure how much logic should i put into controller and how in this scenario validate if Authentication is admin.</p>
  
  <p>The second one - not sure what to say, for me it is too complicated and i had to inject service class to validation classes or annotation (not sure if it is good practice) but it should work.</p>
  
  <p>Third one - I am putting all logic into service and throwing 2 exception which are RUNTIME EXCEPTION and are connected to controller and controllerAdvice because on those exception depends result of calling endpoint.</p>
  
  <p>I would be glad for some tips how to proper solved this and any feedback about code and project architecture. 
  Most of the current code is available here:
  <a href="https://github.com/hadson172/springwebapp/" rel="nofollow noreferrer" title="Github">Github</a></p>