Skip to content

Commit 156d93b

Browse files
author
bnasslahsen
committed
assignableTypes attribute in @ControllerAdvice. Fixes #588.
1 parent 1733bf9 commit 156d93b

25 files changed

+1787
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package org.springdoc.core;
2+
3+
import java.util.LinkedHashMap;
4+
import java.util.Map;
5+
6+
import io.swagger.v3.oas.models.responses.ApiResponse;
7+
8+
import org.springframework.web.bind.annotation.ControllerAdvice;
9+
10+
public class ControllerAdviceInfo {
11+
12+
private ControllerAdvice controllerAdvice;
13+
14+
private Map<String, ApiResponse> apiResponseMap = new LinkedHashMap<>();
15+
16+
public ControllerAdviceInfo(ControllerAdvice controllerAdvice) {
17+
this.controllerAdvice = controllerAdvice;
18+
}
19+
20+
public ControllerAdvice getControllerAdvice() {
21+
return controllerAdvice;
22+
}
23+
24+
public Map<String, ApiResponse> getApiResponseMap() {
25+
return apiResponseMap;
26+
}
27+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package sample;
2+
3+
import java.util.Arrays;
4+
import java.util.Collections;
5+
import java.util.List;
6+
7+
8+
public class ErrorMessage {
9+
10+
private List<String> errors;
11+
12+
public ErrorMessage() {
13+
}
14+
15+
public ErrorMessage(List<String> errors) {
16+
this.errors = errors;
17+
}
18+
19+
public ErrorMessage(String error) {
20+
this(Collections.singletonList(error));
21+
}
22+
23+
public ErrorMessage(String ... errors) {
24+
this(Arrays.asList(errors));
25+
}
26+
27+
public List<String> getErrors() {
28+
return errors;
29+
}
30+
31+
public void setErrors(List<String> errors) {
32+
this.errors = errors;
33+
}
34+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package sample;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.Set;
6+
import java.util.UUID;
7+
8+
import javax.validation.ConstraintViolation;
9+
import javax.validation.ConstraintViolationException;
10+
11+
import org.slf4j.Logger;
12+
import org.slf4j.LoggerFactory;
13+
import org.springframework.http.HttpStatus;
14+
import org.springframework.http.MediaType;
15+
import org.springframework.http.ResponseEntity;
16+
import org.springframework.http.converter.HttpMessageNotReadableException;
17+
import org.springframework.validation.FieldError;
18+
import org.springframework.validation.ObjectError;
19+
import org.springframework.web.HttpMediaTypeNotSupportedException;
20+
import org.springframework.web.bind.MethodArgumentNotValidException;
21+
import org.springframework.web.bind.MissingServletRequestParameterException;
22+
import org.springframework.web.bind.annotation.ControllerAdvice;
23+
import org.springframework.web.bind.annotation.ExceptionHandler;
24+
import org.springframework.web.bind.annotation.RequestMapping;
25+
import org.springframework.web.bind.annotation.ResponseStatus;
26+
27+
28+
29+
@ControllerAdvice()
30+
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
31+
public class GlobalControllerAdvice //extends ResponseEntityExceptionHandler
32+
{
33+
/**
34+
* Note use base class if you wish to leverage its handling.
35+
* Some code will need changing.
36+
*/
37+
private static final Logger logger = LoggerFactory.getLogger(GlobalControllerAdvice.class);
38+
39+
@ExceptionHandler(Throwable.class)
40+
@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
41+
public ResponseEntity < Problem > problem(final Throwable e) {
42+
String message =e.getMessage();
43+
//might actually prefer to use a geeric mesasge
44+
45+
message="Problem occured";
46+
UUID uuid = UUID.randomUUID();
47+
String logRef=uuid.toString();
48+
logger.error("logRef="+logRef, message, e);
49+
return new ResponseEntity <Problem> (new Problem(logRef, message), HttpStatus.INTERNAL_SERVER_ERROR);
50+
}
51+
52+
53+
54+
@ExceptionHandler(MethodArgumentNotValidException.class)
55+
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
56+
public ResponseEntity<ErrorMessage> handleMethodArgumentNotValid(MethodArgumentNotValidException ex
57+
) {
58+
List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();
59+
List<ObjectError> globalErrors = ex.getBindingResult().getGlobalErrors();
60+
List<String> errors = new ArrayList<>(fieldErrors.size() + globalErrors.size());
61+
String error;
62+
for (FieldError fieldError : fieldErrors) {
63+
error = fieldError.getField() + ", " + fieldError.getDefaultMessage();
64+
errors.add(error);
65+
}
66+
for (ObjectError objectError : globalErrors) {
67+
error = objectError.getObjectName() + ", " + objectError.getDefaultMessage();
68+
errors.add(error);
69+
}
70+
ErrorMessage errorMessage = new ErrorMessage(errors);
71+
72+
//Object result=ex.getBindingResult();//instead of above can allso pass the more detailed bindingResult
73+
return new ResponseEntity(errorMessage, HttpStatus.BAD_REQUEST);
74+
}
75+
@ExceptionHandler(ConstraintViolationException.class)
76+
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
77+
public ResponseEntity<ErrorMessage> handleConstraintViolatedException(ConstraintViolationException ex
78+
) {
79+
Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
80+
81+
82+
List<String> errors = new ArrayList<>(constraintViolations.size() );
83+
String error;
84+
for (ConstraintViolation constraintViolation : constraintViolations) {
85+
86+
error = constraintViolation.getMessage();
87+
errors.add(error);
88+
}
89+
90+
ErrorMessage errorMessage = new ErrorMessage(errors);
91+
return new ResponseEntity(errorMessage, HttpStatus.BAD_REQUEST);
92+
}
93+
94+
@ExceptionHandler(MissingServletRequestParameterException.class)
95+
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
96+
public ResponseEntity<ErrorMessage> handleMissingServletRequestParameterException(MissingServletRequestParameterException ex
97+
) {
98+
99+
List<String> errors = new ArrayList<>( );
100+
String error=ex.getParameterName()+", "+ex.getMessage();
101+
errors.add(error);
102+
ErrorMessage errorMessage = new ErrorMessage(errors);
103+
return new ResponseEntity(errorMessage, HttpStatus.BAD_REQUEST);
104+
}
105+
106+
107+
@ExceptionHandler(HttpMediaTypeNotSupportedException.class)
108+
@ResponseStatus(code = HttpStatus.UNSUPPORTED_MEDIA_TYPE)
109+
public ResponseEntity<ErrorMessage> handleHttpMediaTypeNotSupported(HttpMediaTypeNotSupportedException ex
110+
) {
111+
String unsupported = "Unsupported content type: " + ex.getContentType();
112+
String supported = "Supported content types: " + MediaType.toString(ex.getSupportedMediaTypes());
113+
ErrorMessage errorMessage = new ErrorMessage(unsupported, supported);
114+
return new ResponseEntity(errorMessage, HttpStatus.UNSUPPORTED_MEDIA_TYPE);
115+
}
116+
117+
@ExceptionHandler(HttpMessageNotReadableException.class)
118+
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
119+
public ResponseEntity<ErrorMessage> handleHttpMessageNotReadable(HttpMessageNotReadableException ex) {
120+
Throwable mostSpecificCause = ex.getMostSpecificCause();
121+
ErrorMessage errorMessage;
122+
if (mostSpecificCause != null) {
123+
String exceptionName = mostSpecificCause.getClass().getName();
124+
String message = mostSpecificCause.getMessage();
125+
errorMessage = new ErrorMessage(exceptionName, message);
126+
} else {
127+
errorMessage = new ErrorMessage(ex.getMessage());
128+
}
129+
return new ResponseEntity(errorMessage, HttpStatus.BAD_REQUEST);
130+
}
131+
132+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package sample;
2+
3+
import javax.validation.constraints.Email;
4+
import javax.validation.constraints.Max;
5+
import javax.validation.constraints.Min;
6+
import javax.validation.constraints.NotBlank;
7+
import javax.validation.constraints.NotNull;
8+
import javax.validation.constraints.Pattern;
9+
import javax.validation.constraints.Size;
10+
11+
12+
import org.hibernate.validator.constraints.CreditCardNumber;
13+
14+
15+
public class Person {
16+
private long id;
17+
private String firstName;
18+
@NotNull
19+
@NotBlank
20+
@Size(max = 10)
21+
private String lastName;
22+
@Pattern(regexp = ".+@.+\\..+", message = "Please provide a valid email address")
23+
private String email;
24+
@Email()
25+
private String email1;
26+
@Min(18)
27+
@Max(30)
28+
private int age;
29+
@CreditCardNumber
30+
private String creditCardNumber;
31+
32+
public String getCreditCardNumber() {
33+
return creditCardNumber;
34+
}
35+
36+
public void setCreditCardNumber(String creditCardNumber) {
37+
this.creditCardNumber = creditCardNumber;
38+
}
39+
40+
public long getId() {
41+
return id;
42+
}
43+
44+
public void setId(long id) {
45+
this.id = id;
46+
}
47+
48+
public String getEmail1() {
49+
return email1;
50+
}
51+
52+
public void setEmail1(String email1) {
53+
this.email1 = email1;
54+
}
55+
56+
@Size(min = 2)
57+
public String getFirstName() {
58+
return firstName;
59+
}
60+
61+
public void setFirstName(String firstName) {
62+
this.firstName = firstName;
63+
}
64+
65+
public String getLastName() {
66+
return lastName;
67+
}
68+
69+
public void setLastName(String lastName) {
70+
this.lastName = lastName;
71+
}
72+
73+
public String getEmail() {
74+
return email;
75+
}
76+
77+
public void setEmail(String email) {
78+
this.email = email;
79+
}
80+
81+
public int getAge() {
82+
return age;
83+
}
84+
85+
public void setAge(int age) {
86+
this.age = age;
87+
}
88+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package sample;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.Random;
6+
7+
import javax.validation.Valid;
8+
import javax.validation.constraints.NotBlank;
9+
import javax.validation.constraints.NotNull;
10+
import javax.validation.constraints.Size;
11+
12+
import org.springframework.validation.annotation.Validated;
13+
import org.springframework.web.bind.annotation.RequestBody;
14+
import org.springframework.web.bind.annotation.RequestMapping;
15+
import org.springframework.web.bind.annotation.RequestMethod;
16+
import org.springframework.web.bind.annotation.RequestParam;
17+
import org.springframework.web.bind.annotation.RestController;
18+
19+
@RestController
20+
@Validated
21+
public class PersonController {
22+
private Random ran = new Random();
23+
@RequestMapping(path = "/person", method = RequestMethod.POST)
24+
public Person person(@Valid @RequestBody Person person) {
25+
26+
int nxt = ran.nextInt(10);
27+
if(nxt>=5)
28+
{
29+
throw new RuntimeException("Breaking logic");
30+
}
31+
return person;
32+
}
33+
@RequestMapping(path = "/personByLastName", method = RequestMethod.GET)
34+
public List<Person> findByLastName(@RequestParam(name = "lastName", required = true)@NotNull
35+
@NotBlank
36+
@Size(max = 10)String lastName){
37+
List<Person> hardCoded= new ArrayList<>();
38+
Person person= new Person();
39+
person.setAge(20);
40+
person.setCreditCardNumber("4111111111111111");
41+
person.setEmail("abc@abc.com");
42+
person.setEmail1("abc1@abc.com");
43+
person.setFirstName("Somefirstname");
44+
person.setLastName(lastName);
45+
person.setId(1);
46+
hardCoded.add(person);
47+
return hardCoded;
48+
49+
}
50+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package sample;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.Random;
6+
7+
import javax.validation.Valid;
8+
import javax.validation.constraints.NotBlank;
9+
import javax.validation.constraints.NotNull;
10+
import javax.validation.constraints.Size;
11+
12+
import org.springframework.validation.annotation.Validated;
13+
import org.springframework.web.bind.annotation.RequestBody;
14+
import org.springframework.web.bind.annotation.RequestMapping;
15+
import org.springframework.web.bind.annotation.RequestMethod;
16+
import org.springframework.web.bind.annotation.RequestParam;
17+
import org.springframework.web.bind.annotation.RestController;
18+
19+
@RestController
20+
@Validated
21+
public class PersonController2 {
22+
private Random ran = new Random();
23+
@RequestMapping(path = "/person2", method = RequestMethod.POST)
24+
public Person person(@Valid @RequestBody Person person) {
25+
26+
int nxt = ran.nextInt(10);
27+
if(nxt>=5)
28+
{
29+
throw new RuntimeException("Breaking logic");
30+
}
31+
return person;
32+
}
33+
@RequestMapping(path = "/personByLastName2", method = RequestMethod.GET)
34+
public List<Person> findByLastName(@RequestParam(name = "lastName", required = true)@NotNull
35+
@NotBlank
36+
@Size(max = 10)String lastName){
37+
List<Person> hardCoded= new ArrayList<>();
38+
Person person= new Person();
39+
person.setAge(20);
40+
person.setCreditCardNumber("4111111111111111");
41+
person.setEmail("abc@abc.com");
42+
person.setEmail1("abc1@abc.com");
43+
person.setFirstName("Somefirstname");
44+
person.setLastName(lastName);
45+
person.setId(1);
46+
hardCoded.add(person);
47+
return hardCoded;
48+
49+
}
50+
}

0 commit comments

Comments
 (0)