Explorar el Código

at part 5 and I'm almost done

Whitney Martinez hace 5 años
padre
commit
3b33c7c7e2

+ 4
- 4
README.md Ver fichero

@@ -461,7 +461,7 @@ public class ComputeResultController {
461 461
 
462 462
 ## Part 5.1 - Create `ResourceNotFoundException`
463 463
 
464
-- Create a `exception` package inside of `io.zipcoder.springdemo.QuickPollApplication`
464
+- Create a `io.zipcoder.tc_spring_poll_application.exception` package inside of `io.zipcoder.springdemo.QuickPollApplication`
465 465
 - Create a `ResourceNotFoundException` class that extends `RuntimeException`. We'll use this to signal when a requested resource is not found.
466 466
 - Annotate the `ResourceNotFoundException` class with `@ResponseStatus(HttpStatus.NOT_FOUND)`. This informs Spring that any request mapping that throws a `ResourceNotFoundException` should result in a `404 NOT FOUND` http status.
467 467
 - Implement three constructors
@@ -478,7 +478,7 @@ Create a void method in `PollController` called `verifyPoll` that checks if a sp
478 478
 
479 479
 ## Part 5.3 - Create custom Error Responses
480 480
 
481
-Spring provides some built-in exception handling and error response, but we'll customize it a bit here. Create an `ErrorDetail` class in a new `io.zipcoder.tc_spring_poll_application.dto.error` package to hold relevant information any time an error occurs.
481
+Spring provides some built-in io.zipcoder.tc_spring_poll_application.exception handling and error response, but we'll customize it a bit here. Create an `ErrorDetail` class in a new `io.zipcoder.tc_spring_poll_application.dto.error` package to hold relevant information any time an error occurs.
482 482
 
483 483
 Fields (Don't forget to provide getters and setters):
484 484
 
@@ -486,12 +486,12 @@ Fields (Don't forget to provide getters and setters):
486 486
 - `int status`: the HTTP status code for the current request; redundant but useful for client-side error handling
487 487
 - `String detail`: A short, human-readable description of the error that may be presented to a user
488 488
 - `long timeStamp`: the time in milliseconds when the error occurred
489
-- `String developerMessage`: detailed information such as exception class name or a stack trace useful for developers to debug
489
+- `String developerMessage`: detailed information such as io.zipcoder.tc_spring_poll_application.exception class name or a stack trace useful for developers to debug
490 490
 
491 491
 
492 492
 ## Part 5.4 - Create a `@ControllerAdvice`
493 493
 
494
-In this section we add custom handling for the exceptions we created before. A `@ControllerAdvice` is an AOP feature that wraps a controller and adds some functionality when needed. In this case we are adding functionality only when an exception is thrown.
494
+In this section we add custom handling for the exceptions we created before. A `@ControllerAdvice` is an AOP feature that wraps a controller and adds some functionality when needed. In this case we are adding functionality only when an io.zipcoder.tc_spring_poll_application.exception is thrown.
495 495
 
496 496
 - Create RestExceptionHandler class annotated with `@ControllerAdvice`
497 497
 - Create a handler method with the header shown below

+ 4
- 0
src/main/java/io/zipcoder/tc_spring_poll_application/controller/ControllerAdvice.java Ver fichero

@@ -0,0 +1,4 @@
1
+package io.zipcoder.tc_spring_poll_application.controller;
2
+
3
+public class ControllerAdvice {
4
+}

+ 16
- 8
src/main/java/io/zipcoder/tc_spring_poll_application/controller/PollController.java Ver fichero

@@ -9,6 +9,7 @@ import org.springframework.http.HttpStatus;
9 9
 import org.springframework.http.ResponseEntity;
10 10
 import org.springframework.web.bind.annotation.*;
11 11
 import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
12
+import io.zipcoder.tc_spring_poll_application.exception.ResourceNotFoundError;
12 13
 
13 14
 import javax.validation.Valid;
14 15
 import java.net.URI;
@@ -17,7 +18,7 @@ import java.net.URI;
17 18
 @RestController
18 19
 public class PollController {
19 20
 
20
-    public PollRepository pollRepository;
21
+    private PollRepository pollRepository;
21 22
 
22 23
     @Autowired
23 24
     public PollController(PollRepository pollRepository) {
@@ -50,28 +51,35 @@ public class PollController {
50 51
     @RequestMapping(value = "/polls/{pollId}", method = RequestMethod.GET)
51 52
     public ResponseEntity<?> getPoll(@PathVariable Long pollId) {
52 53
         Poll p = pollRepository.findOne(pollId);
54
+        verifyPoll(pollId);
53 55
         return new ResponseEntity<>(p, HttpStatus.OK);
54 56
     }
55 57
 
56 58
     @RequestMapping(value = "/polls/{pollId}", method = RequestMethod.PUT)
57
-    public ResponseEntity<?> updatePoll(@RequestBody Poll poll, @PathVariable Long pollId) {
59
+    public ResponseEntity<?> updatePoll(@Valid @RequestBody Poll poll, @PathVariable Long pollId) {
58 60
         // Save the entity
59 61
 
60 62
         Poll p = pollRepository.save(poll);
63
+        verifyPoll(pollId);
61 64
         return new ResponseEntity<>(HttpStatus.OK);
62 65
     }
63 66
 
64 67
     @RequestMapping(value = "/polls/{pollId}", method = RequestMethod.DELETE)
65 68
     public ResponseEntity<?> deletePoll(@PathVariable Long pollId) {
66 69
         pollRepository.delete(pollId);
70
+        verifyPoll(pollId);
67 71
         return new ResponseEntity<>(HttpStatus.OK);
68 72
     }
69
-//    protected void verifyPoll(Long pollId) throws ResourceNotFoundException{
70
-//        Poll poll = pollRepository.findOne(pollId);
71
-//        if(poll == null){
72
-//            throw new ResourceNotFoundException("Poll with id "+ pollId + "not found");
73
-//        }
74
-//    }
73
+
74
+    //io.zipcoder.tc_spring_poll_application.exception.ResourceNotFoundError
75
+    protected void verifyPoll(Long pollId) throws ResourceNotFoundError {
76
+        Poll poll = pollRepository.findOne(pollId);
77
+        if (poll == null) {
78
+            throw new ResourceNotFoundError("Poll with id " + pollId + " not found");
79
+        }
80
+    }
81
+
82
+
75 83
 
76 84
 
77 85
 }

+ 3
- 1
src/main/java/io/zipcoder/tc_spring_poll_application/domain/Poll.java Ver fichero

@@ -1,5 +1,7 @@
1 1
 package io.zipcoder.tc_spring_poll_application.domain;
2
-
2
+import org.hibernate.validator.constraints.NotEmpty;
3
+import javax.validation.constraints.Size;
4
+import javax.validation.Valid;
3 5
 
4 6
 import org.hibernate.validator.constraints.NotEmpty;
5 7
 

+ 71
- 0
src/main/java/io/zipcoder/tc_spring_poll_application/dto/error/ErrorDetail.java Ver fichero

@@ -0,0 +1,71 @@
1
+package io.zipcoder.tc_spring_poll_application.dto.error;
2
+
3
+import org.springframework.http.HttpStatus;
4
+
5
+import java.util.List;
6
+import java.util.Map;
7
+
8
+public class ErrorDetail {
9
+
10
+    private String title;
11
+
12
+    private String detail;
13
+
14
+    private String developerMessage;
15
+    private long timeStamp;
16
+    private int status;
17
+    private Map<String, List<ValidationError>> errors;
18
+
19
+    public Map<String, List<ValidationError>> getErrors() {
20
+        return errors;
21
+    }
22
+
23
+    public void setErrors(Map<String, List<ValidationError>> errors) {
24
+        this.errors = errors;
25
+    }
26
+
27
+    public String getTitle() {
28
+        return title;
29
+    }
30
+
31
+    public void setTitle(String title) {
32
+        this.title = title;
33
+    }
34
+
35
+
36
+
37
+    public String getDetail() {
38
+        return detail;
39
+    }
40
+
41
+    public void setDetail(String detail) {
42
+        this.detail = detail;
43
+    }
44
+
45
+
46
+
47
+
48
+    public String getDeveloperMessage() {
49
+        return developerMessage;
50
+    }
51
+
52
+    public void setDeveloperMessage(String developerMessage) {
53
+        this.developerMessage = developerMessage;
54
+    }
55
+
56
+    public void setTimeStamp(long timeStamp) {
57
+        this.timeStamp = timeStamp;
58
+    }
59
+
60
+    public long getTimeStamp() {
61
+        return timeStamp;
62
+    }
63
+
64
+    public void setStatus(int status) {
65
+        this.status = status;
66
+    }
67
+
68
+    public int getStatus() {
69
+        return status;
70
+    }
71
+}

+ 23
- 0
src/main/java/io/zipcoder/tc_spring_poll_application/dto/error/ValidationError.java Ver fichero

@@ -0,0 +1,23 @@
1
+package io.zipcoder.tc_spring_poll_application.dto.error;
2
+
3
+public class ValidationError {
4
+
5
+    String code;
6
+    String message;
7
+
8
+    public String getCode() {
9
+        return code;
10
+    }
11
+
12
+    public void setCode(String code) {
13
+        this.code = code;
14
+    }
15
+
16
+    public String getMessage() {
17
+        return message;
18
+    }
19
+
20
+    public void setMessage(String message) {
21
+        this.message = message;
22
+    }
23
+}

+ 25
- 0
src/main/java/io/zipcoder/tc_spring_poll_application/exception/ResourceNotFoundError.java Ver fichero

@@ -0,0 +1,25 @@
1
+package io.zipcoder.tc_spring_poll_application.exception;
2
+
3
+import org.springframework.http.HttpStatus;
4
+import org.springframework.web.bind.annotation.ResponseStatus;
5
+
6
+@ResponseStatus(HttpStatus.NOT_FOUND)
7
+public class ResourceNotFoundError extends RuntimeException {
8
+
9
+
10
+
11
+
12
+    public ResourceNotFoundError(){
13
+
14
+    }
15
+
16
+    public ResourceNotFoundError(String message){
17
+        super(message);
18
+    }
19
+
20
+    public ResourceNotFoundError(String message, Throwable cause){
21
+
22
+        super(message,cause);
23
+    }
24
+
25
+}

+ 76
- 0
src/main/java/io/zipcoder/tc_spring_poll_application/exception/RestExceptionHandler.java Ver fichero

@@ -0,0 +1,76 @@
1
+package io.zipcoder.tc_spring_poll_application.exception;
2
+
3
+import io.zipcoder.tc_spring_poll_application.dto.error.ErrorDetail;
4
+import io.zipcoder.tc_spring_poll_application.dto.error.ValidationError;
5
+import org.springframework.context.MessageSource;
6
+import org.springframework.http.HttpStatus;
7
+import org.springframework.http.ResponseEntity;
8
+import org.springframework.validation.FieldError;
9
+import org.springframework.web.bind.MethodArgumentNotValidException;
10
+import org.springframework.web.bind.annotation.ControllerAdvice;
11
+import org.springframework.web.bind.annotation.ExceptionHandler;
12
+import org.springframework.web.bind.annotation.ResponseBody;
13
+import org.springframework.web.bind.annotation.ResponseStatus;
14
+
15
+import javax.servlet.http.HttpServlet;
16
+import javax.servlet.http.HttpServletRequest;
17
+import java.util.ArrayList;
18
+import java.util.Date;
19
+import java.util.List;
20
+
21
+@ControllerAdvice
22
+public class RestExceptionHandler {
23
+
24
+    private MessageSource messageSource;
25
+
26
+
27
+    @ExceptionHandler(ResourceNotFoundError.class)
28
+    ResponseEntity<?> ResourceNotFoundError(ResourceNotFoundError rnfe, HttpServletRequest request) throws Exception{
29
+
30
+        ErrorDetail errors = new ErrorDetail();
31
+
32
+        errors.setTimeStamp(new Date().getTime());
33
+        errors.setStatus(HttpStatus.NOT_FOUND.value());
34
+        errors.setTitle("Resource not Found");
35
+        errors.setDetail(rnfe.getMessage());
36
+        errors.setDeveloperMessage(rnfe.getClass().getName());
37
+
38
+        return new ResponseEntity<>(errors,null,HttpStatus.NOT_FOUND);
39
+
40
+    }
41
+    @ExceptionHandler(MethodArgumentNotValidException.class)
42
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
43
+    public @ResponseBody
44
+    ErrorDetail handleValidationError(  MethodArgumentNotValidException manve, HttpServletRequest request){
45
+
46
+        ErrorDetail errorDetail = new ErrorDetail();
47
+        errorDetail.setTimeStamp(new Date().getTime());
48
+        errorDetail.setStatus(HttpStatus.BAD_REQUEST.value());
49
+        String requestPath = (String) request.getAttribute("java.servlet.error.request_uri");
50
+
51
+        if(requestPath == null){
52
+            requestPath = request.getRequestURI();
53
+        }
54
+
55
+        errorDetail.setTitle("Bad entry, Validating Error");
56
+        errorDetail.setDetail("Input validation fail");
57
+        errorDetail.setDeveloperMessage(manve.getClass().getName());
58
+
59
+        List<FieldError> fieldErrors =  manve.getBindingResult().getFieldErrors();
60
+        for(FieldError fe : fieldErrors) {
61
+
62
+            List<ValidationError> validationErrorList = errorDetail.getErrors().get(fe.getField());
63
+            if(validationErrorList == null) {
64
+                validationErrorList = new ArrayList<ValidationError>();
65
+                errorDetail.getErrors().put(fe.getField(), validationErrorList);
66
+            }
67
+            ValidationError validationError = new ValidationError();
68
+            validationError.setCode(fe.getCode());
69
+            validationError.setMessage(messageSource.getMessage(fe, null));
70
+            validationErrorList.add(validationError);
71
+        }
72
+        return errorDetail;
73
+    }
74
+
75
+
76
+}

+ 15
- 0
src/test/java/io/zipcoder/tc_spring_poll_application/exception/ResourceNotFoundExceptionTest.java Ver fichero

@@ -0,0 +1,15 @@
1
+package io.zipcoder.tc_spring_poll_application.exception;
2
+
3
+import org.springframework.boot.context.config.ResourceNotFoundException;
4
+import org.springframework.core.io.Resource;
5
+
6
+public class ResourceNotFoundExceptionTest extends ResourceNotFoundException {
7
+
8
+    
9
+
10
+
11
+
12
+    public ResourceNotFoundExceptionTest(String propertyName, Resource resource) {
13
+        super(propertyName, resource);
14
+    }
15
+}