浏览代码

completed Lab

mpierse 5 年前
父节点
当前提交
184a28bef6

+ 3
- 1
pom.xml 查看文件

@@ -7,6 +7,7 @@
7 7
     <groupId>io.zipcoder</groupId>
8 8
     <artifactId>spring-demo</artifactId>
9 9
     <version>1.0-SNAPSHOT</version>
10
+
10 11
     <parent>
11 12
         <groupId>org.springframework.boot</groupId>
12 13
         <artifactId>spring-boot-starter-parent</artifactId>
@@ -16,8 +17,9 @@
16 17
     <properties>
17 18
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18 19
         <start-class>io.zipcoder.tc_spring_poll_application.QuickPollApplication</start-class>
19
-        <java.version>1.7</java.version>
20
+        <java.version>1.8</java.version>
20 21
     </properties>
22
+
21 23
     <dependencies>
22 24
         <dependency>
23 25
             <groupId>org.springframework.boot</groupId>

+ 75
- 0
src/main/java/io/zipcoder/tc_spring_poll_application/ErrorDetail.java 查看文件

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

+ 52
- 0
src/main/java/io/zipcoder/tc_spring_poll_application/RestExceptionhandler.java 查看文件

@@ -0,0 +1,52 @@
1
+package io.zipcoder.tc_spring_poll_application;
2
+
3
+import io.zipcoder.tc_spring_poll_application.dtos.ValidationError;
4
+import io.zipcoder.tc_spring_poll_application.exception.ResourceNotFoundException;
5
+import org.springframework.beans.factory.annotation.Autowired;
6
+import org.springframework.context.MessageSource;
7
+import org.springframework.http.HttpStatus;
8
+import org.springframework.http.ResponseEntity;
9
+import org.springframework.validation.FieldError;
10
+import org.springframework.web.bind.MethodArgumentNotValidException;
11
+import org.springframework.web.bind.annotation.ControllerAdvice;
12
+import org.springframework.web.bind.annotation.ExceptionHandler;
13
+
14
+import javax.servlet.http.HttpServletRequest;
15
+import java.util.ArrayList;
16
+import java.util.Date;
17
+import java.util.List;
18
+
19
+@ControllerAdvice
20
+public class RestExceptionhandler {
21
+
22
+    @Autowired
23
+    MessageSource messageSource;
24
+
25
+    @ExceptionHandler(ResourceNotFoundException.class)
26
+    public ResponseEntity<?> handleResourceNotFoundException(ResourceNotFoundException rnfe, HttpServletRequest request) {
27
+        ErrorDetail errorDetail = new ErrorDetail(request.getMethod(), 404, rnfe.getMessage(), new Date().getTime(), rnfe.getStackTrace().toString());
28
+        return new ResponseEntity<>(errorDetail, HttpStatus.NOT_FOUND);
29
+    }
30
+
31
+    @ExceptionHandler(MethodArgumentNotValidException.class)
32
+    public ResponseEntity<?> handleValidationError(MethodArgumentNotValidException manve, HttpServletRequest request){
33
+        ErrorDetail errorDetail = new ErrorDetail();
34
+        errorDetail.setTimestamp(new Date().getTime());
35
+        errorDetail.setDeveloperMessage(manve.getMessage());
36
+        errorDetail.setDetail(manve.getCause().getMessage());
37
+
38
+        List<FieldError> fieldErrors = manve.getBindingResult().getFieldErrors();
39
+        for(FieldError fe : fieldErrors) {
40
+            List<ValidationError> validationErrorList = errorDetail.getErrors().computeIfAbsent(fe.getField(), k -> new ArrayList<>());
41
+
42
+            ValidationError validationError = new ValidationError(null, messageSource.getMessage(fe, null));
43
+            validationError.setCode(fe.getCode());
44
+            validationError.setMessage(messageSource.getMessage(fe, null));
45
+            validationErrorList.add(validationError);
46
+        }
47
+
48
+        return new ResponseEntity<>(errorDetail,HttpStatus.BAD_REQUEST);
49
+    }
50
+
51
+
52
+}

+ 7
- 5
src/main/java/io/zipcoder/tc_spring_poll_application/controller/PollController.java 查看文件

@@ -4,11 +4,13 @@ import io.zipcoder.tc_spring_poll_application.domain.Poll;
4 4
 import io.zipcoder.tc_spring_poll_application.exception.ResourceNotFoundException;
5 5
 import io.zipcoder.tc_spring_poll_application.repositories.PollRepository;
6 6
 import org.springframework.beans.factory.annotation.Autowired;
7
+import org.springframework.data.domain.PageRequest;
7 8
 import org.springframework.http.HttpHeaders;
8 9
 import org.springframework.http.HttpStatus;
9 10
 import org.springframework.http.ResponseEntity;
10 11
 import org.springframework.web.bind.annotation.*;
11 12
 import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
13
+import javax.validation.Valid;
12 14
 import java.net.URI;
13 15
 
14 16
 @RestController
@@ -23,12 +25,12 @@ public class PollController {
23 25
 
24 26
     @RequestMapping(value="/polls", method= RequestMethod.GET)
25 27
     public ResponseEntity<Iterable<Poll>> getAllPolls() {
26
-        Iterable<Poll> allPolls = pollRepository.findAll();
28
+        Iterable<Poll> allPolls = pollRepository.findAll(new PageRequest(0,3));
27 29
         return new ResponseEntity<>(allPolls, HttpStatus.OK);
28 30
     }
29 31
 
30 32
     @RequestMapping(value="/polls", method=RequestMethod.POST)
31
-    public ResponseEntity<?> createPoll(@RequestBody Poll poll) {
33
+    public ResponseEntity<?> createPoll(@RequestBody @Valid Poll poll) {
32 34
         poll = pollRepository.save(poll);
33 35
         URI newPollUri = ServletUriComponentsBuilder
34 36
                 .fromCurrentRequest()
@@ -48,7 +50,7 @@ public class PollController {
48 50
     }
49 51
 
50 52
     @RequestMapping(value="/polls/{pollId}", method=RequestMethod.PUT)
51
-    public ResponseEntity<?> updatePoll(@RequestBody Poll poll, @PathVariable Long pollId) {
53
+    public ResponseEntity<?> updatePoll(@RequestBody @Valid Poll poll, @PathVariable Long pollId) {
52 54
         // Save the entity
53 55
         verifyPoll(pollId);
54 56
         Poll p = pollRepository.save(poll);
@@ -62,7 +64,7 @@ public class PollController {
62 64
         return new ResponseEntity<>(HttpStatus.OK);
63 65
     }
64 66
 
65
-    public void verifyPoll(Long id){
66
-        if(!pollRepository.exists(id)) throw ResourceNotFoundException;
67
+     void verifyPoll(Long id){
68
+        if(!pollRepository.exists(id)) throw new ResourceNotFoundException();
67 69
     }
68 70
 }

+ 5
- 0
src/main/java/io/zipcoder/tc_spring_poll_application/domain/Poll.java 查看文件

@@ -1,6 +1,9 @@
1 1
 package io.zipcoder.tc_spring_poll_application.domain;
2 2
 
3
+import org.hibernate.validator.constraints.NotEmpty;
4
+
3 5
 import javax.persistence.*;
6
+import javax.validation.constraints.Size;
4 7
 import java.util.Set;
5 8
 
6 9
 @Entity
@@ -12,11 +15,13 @@ public class Poll {
12 15
     private Long id;
13 16
 
14 17
     @Column(name = "QUESTION")
18
+    @NotEmpty
15 19
     private String question;
16 20
 
17 21
     @OneToMany(cascade = CascadeType.ALL)
18 22
     @JoinColumn(name = "POLL_ID")
19 23
     @OrderBy
24
+    @Size(min = 2, max = 6)
20 25
     private Set<Option> options;
21 26
 
22 27
     public Long getId() {

+ 28
- 0
src/main/java/io/zipcoder/tc_spring_poll_application/dtos/ValidationError.java 查看文件

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

+ 2
- 1
src/main/java/io/zipcoder/tc_spring_poll_application/repositories/PollRepository.java 查看文件

@@ -2,6 +2,7 @@ package io.zipcoder.tc_spring_poll_application.repositories;
2 2
 
3 3
 import io.zipcoder.tc_spring_poll_application.domain.Poll;
4 4
 import org.springframework.data.repository.CrudRepository;
5
+import org.springframework.data.repository.PagingAndSortingRepository;
5 6
 
6
-public interface PollRepository extends CrudRepository<Poll, Long> {
7
+public interface PollRepository extends PagingAndSortingRepository<Poll, Long> {
7 8
 }

+ 24
- 0
src/main/resources/import.sql 查看文件

@@ -0,0 +1,24 @@
1
+insert into poll (poll_id, question) values (1, 'What is your favorite color?');
2
+insert into option (option_id, option_value, poll_id) values (1, 'Red', 1);
3
+insert into option (option_id, option_value, poll_id) values (2, 'Blue', 1);
4
+insert into option (option_id, option_value, poll_id) values (3, 'Yellow', 1);
5
+insert into poll (poll_id, question) values (2, 'What is your favorite food?');
6
+insert into option (option_id, option_value, poll_id) values (4, 'Pizza', 2);
7
+insert into option (option_id, option_value, poll_id) values (5, 'Carrots', 2);
8
+insert into option (option_id, option_value, poll_id) values (6, 'Candy', 2);
9
+insert into poll (poll_id, question) values (3, 'What is your favorite animal?');
10
+insert into option (option_id, option_value, poll_id) values (7, 'Dog', 3);
11
+insert into option (option_id, option_value, poll_id) values (8, 'Cat', 3);
12
+insert into option (option_id, option_value, poll_id) values (9, 'Mouse', 3);
13
+insert into poll (poll_id, question) values (4, 'What is your favorite thing?');
14
+insert into option (option_id, option_value, poll_id) values (10, 'thing1', 4);
15
+insert into option (option_id, option_value, poll_id) values (11, 'thing2', 4);
16
+insert into option (option_id, option_value, poll_id) values (3, 'thing3', 4);
17
+insert into poll (poll_id, question) values (5, 'What is your favorite Cat?');
18
+insert into option (option_id, option_value, poll_id) values (12, 'cute', 5);
19
+insert into option (option_id, option_value, poll_id) values (13, 'fluffy', 5);
20
+insert into option (option_id, option_value, poll_id) values (14, 'mean', 5);
21
+insert into poll (poll_id, question) values (6, 'What is your favorite road?');
22
+insert into option (option_id, option_value, poll_id) values (15, 'this road', 6);
23
+insert into option (option_id, option_value, poll_id) values (16, 'that road', 6);
24
+insert into option (option_id, option_value, poll_id) values (17, 'no road', 6);

+ 2
- 0
src/main/resources/messages.properties 查看文件

@@ -0,0 +1,2 @@
1
+NotEmpty.poll.question=Question is a required field
2
+Size.poll.options=Options must be greater than {2} and less than {1}