22
33
44import com .patternknife .securityhelper .oauth2 .client .config .response .error .dto .CustomErrorResponsePayload ;
5- import com .patternknife .securityhelper .oauth2 .client .config .response .error .exception .auth .*;
6- import com .patternknife .securityhelper .oauth2 .client .config .response .error .exception .data .*;
7-
8- import com .patternknife .securityhelper .oauth2 .client .config .response .error .exception .payload .SearchFilterException ;
95
106import com .patternknife .securityhelper .oauth2 .client .config .response .error .message .GeneralErrorMessage ;
11- import jakarta .servlet .http .HttpServletRequest ;
12- import jakarta .validation .ConstraintViolationException ;
7+ import io .github .patternknife .securityhelper .oauth2 .api .config .response .error .ExceptionKnifeUtils ;
8+ import io .github .patternknife .securityhelper .oauth2 .api .config .response .error .dto .ErrorResponsePayload ;
9+ import io .github .patternknife .securityhelper .oauth2 .api .config .response .error .exception .auth .KnifeOauth2AuthenticationException ;
10+ import io .github .patternknife .securityhelper .oauth2 .api .config .security .message .DefaultSecurityUserExceptionMessage ;
11+ import io .github .patternknife .securityhelper .oauth2 .api .config .security .message .ISecurityUserExceptionMessageService ;
12+ import lombok .RequiredArgsConstructor ;;
1313import org .springframework .http .HttpStatus ;
1414import org .springframework .http .ResponseEntity ;
15- import org .springframework .http .converter .HttpMessageNotReadableException ;
16- import org .springframework .validation .BindException ;
17- import org .springframework .validation .FieldError ;
18- import org .springframework .web .bind .MethodArgumentNotValidException ;
19- import org .springframework .web .bind .MissingServletRequestParameterException ;
15+ import org .springframework .security .access .AccessDeniedException ;
16+ import org .springframework .security .core .AuthenticationException ;
2017import org .springframework .web .bind .annotation .ControllerAdvice ;
2118import org .springframework .web .bind .annotation .ExceptionHandler ;
22- import org .springframework .web .client .ResourceAccessException ;
23- import org .springframework .web .context .request .WebRequest ;
2419
25- import java .util .HashMap ;
26- import java .util .Map ;
20+ import org .springframework .web .context .request .WebRequest ;
2721
2822
23+ /*
24+ *
25+ * Customize the exception payload by implementing this, which replaces
26+ * 'io.github.patternknife.securityhelper.oauth2.api.config.response.error.SecurityKnifeExceptionHandler'
27+ *
28+ * Once you create 'GlobalExceptionHandler', you should insert the following two as default. Otherwise, 'unhandledExceptionHandler' is prior to 'io.github.patternknife.securityhelper.oauth2.api.config.response.error.SecurityKnifeExceptionHandler'.
29+ *
30+ * */
2931@ ControllerAdvice
32+ @ RequiredArgsConstructor
3033public class GlobalExceptionHandler {
3134
32-
33- // UserDeletedException : caused by the process of user deactivation
34- // UserRestoredException : caused by the process of user reactivation
35- @ ExceptionHandler ({UserDeletedException .class , UserRestoredException .class })
36- public ResponseEntity <?> activationException (Exception ex , WebRequest request ) {
37- CustomErrorResponsePayload customErrorResponsePayload = new CustomErrorResponsePayload (ex .getMessage () != null ? ex .getMessage () : CustomExceptionUtils .getAllCauses (ex ),
38- request .getDescription (false ),ex .getMessage () , ex .getStackTrace ()[0 ].toString ());
39- return new ResponseEntity <>(customErrorResponsePayload , HttpStatus .FORBIDDEN );
40- }
41-
42-
43- // 2. data
44- @ ExceptionHandler (ResourceNotFoundException .class )
45- public ResponseEntity <?> resourceNotFoundException (ResourceNotFoundException ex , WebRequest request ) {
46-
47- CustomErrorResponsePayload customErrorResponsePayload ;
48- if (ex .getErrorMessages () != null ){
49-
50- customErrorResponsePayload = new CustomErrorResponsePayload (ex .getErrorMessages (),
51- ex , request .getDescription (false ), CustomExceptionUtils .getAllStackTraces (ex ),
52- CustomExceptionUtils .getAllCauses (ex ), null );
53-
54- }else {
55- customErrorResponsePayload = new CustomErrorResponsePayload (ex .getMessage (), request .getDescription (false ),
56- ex .getMessage (), CustomExceptionUtils .getAllStackTraces (ex ),
57- CustomExceptionUtils .getAllCauses (ex ));
35+ private final ISecurityUserExceptionMessageService iSecurityUserExceptionMessageService ;
36+
37+ // 401 : Authentication
38+ @ ExceptionHandler ({AuthenticationException .class })
39+ public ResponseEntity <?> authenticationException (Exception ex , WebRequest request ) {
40+ ErrorResponsePayload errorResponsePayload ;
41+ if (ex instanceof KnifeOauth2AuthenticationException && ((KnifeOauth2AuthenticationException ) ex ).getErrorMessages () != null ) {
42+ errorResponsePayload = new ErrorResponsePayload (((KnifeOauth2AuthenticationException ) ex ).getErrorMessages (),
43+ ex , request .getDescription (false ), ExceptionKnifeUtils .getAllStackTraces (ex ),
44+ ExceptionKnifeUtils .getAllCauses (ex ), null );
45+ }else {
46+ errorResponsePayload = new ErrorResponsePayload (ExceptionKnifeUtils .getAllCauses (ex ), request .getDescription (false ), iSecurityUserExceptionMessageService .getUserMessage (DefaultSecurityUserExceptionMessage .AUTHENTICATION_LOGIN_FAILURE ),
47+ ex .getMessage (), ex .getStackTrace ()[0 ].toString ());
5848 }
59- return new ResponseEntity <>(customErrorResponsePayload , HttpStatus .NOT_FOUND );
60-
61- }
62-
63-
64-
65- @ ExceptionHandler (SearchFilterException .class )
66- public ResponseEntity <?> searchFilterException (SearchFilterException ex , WebRequest request ) {
67-
68- //logger.error(ex.getMessage());
69- CustomErrorResponsePayload customErrorResponsePayload = new CustomErrorResponsePayload (ex .getCause ().getMessage (), request .getDescription (false ),
70- ex .getMessage (), ex .getStackTrace ()[0 ].toString ());
71- return new ResponseEntity <>(customErrorResponsePayload , HttpStatus .BAD_REQUEST );
49+ return new ResponseEntity <>(errorResponsePayload , HttpStatus .UNAUTHORIZED );
7250 }
7351
74-
75-
76- @ ExceptionHandler (NullPointerException .class )
77- public ResponseEntity <?> nullPointerException (NullPointerException ex , WebRequest request ) {
78- CustomErrorResponsePayload customErrorResponsePayload = new CustomErrorResponsePayload (ex .getMessage (), request .getDescription (false ),
79- GeneralErrorMessage .NULL_VALUE_FOUND .getUserMessage (), CustomExceptionUtils .getAllStackTraces (ex ), CustomExceptionUtils .getAllCauses (ex ));
80- return new ResponseEntity <>(customErrorResponsePayload , HttpStatus .NOT_FOUND );
52+ // 403 : Authorization
53+ @ ExceptionHandler ({ AccessDeniedException .class })
54+ public ResponseEntity <?> authorizationException (Exception ex , WebRequest request ) {
55+ ErrorResponsePayload errorResponsePayload = new ErrorResponsePayload (ex .getMessage () != null ? ex .getMessage () : ExceptionKnifeUtils .getAllCauses (ex ), request .getDescription (false ),
56+ ex .getMessage () == null || ex .getMessage ().equals ("Access Denied" ) ? iSecurityUserExceptionMessageService .getUserMessage (DefaultSecurityUserExceptionMessage .AUTHORIZATION_FAILURE ) : ex .getMessage (), ex .getStackTrace ()[0 ].toString ());
57+ return new ResponseEntity <>(errorResponsePayload , HttpStatus .FORBIDDEN );
8158 }
82-
83-
84-
85-
86-
87- // 3. Request @Valid
88- /* 1. Validating the request body (when not using @RequestParam): Error thrown by @Valid. */
89- @ ExceptionHandler (MethodArgumentNotValidException .class )
90- public ResponseEntity <?> methodArgumentNotValidException (MethodArgumentNotValidException ex , WebRequest request ) {
91-
92- Map <String , String > userValidationMessages = CustomExceptionUtils .extractMethodArgumentNotValidErrors (ex );
93-
94- CustomErrorResponsePayload customErrorResponsePayload = new CustomErrorResponsePayload (ex .getMessage (), request .getDescription (false ),
95- null ,
96- userValidationMessages ,
97- CustomExceptionUtils .getAllStackTraces (ex ), CustomExceptionUtils .getAllCauses (ex ));
98- return new ResponseEntity <>(customErrorResponsePayload , HttpStatus .UNPROCESSABLE_ENTITY );
99- }
100- //
101- //The types of individual parameters in the request body (String, Date, Integer) are different, or there is a JSON format error.
102- @ ExceptionHandler (HttpMessageNotReadableException .class )
103- public ResponseEntity <?> httpMessageNotReadableExceptionHandler (HttpMessageNotReadableException ex , WebRequest request ) {
104-
105- CustomErrorResponsePayload customErrorResponsePayload = new CustomErrorResponsePayload (ex .getMessage (), request .getDescription (false ),
106- "The received form does not match. Please contact the administrator with the following information. (Error details: " + ex .getMostSpecificCause ().getMessage () + ")" ,
107- null ,
108- CustomExceptionUtils .getAllStackTraces (ex ), CustomExceptionUtils .getAllCauses (ex ));
109- return new ResponseEntity <>(customErrorResponsePayload , HttpStatus .BAD_REQUEST );
110- }
111-
112- /* 2-1. In the case of @RequestParam: Validity check thrown by @Validated. */
113- @ ExceptionHandler (ConstraintViolationException .class )
114- public ResponseEntity <?> missingServletRequestParameterException (ConstraintViolationException ex , WebRequest request , HttpServletRequest h ) {
115-
116- CustomErrorResponsePayload customErrorResponsePayload = new CustomErrorResponsePayload (ex .getMessage (), request .getDescription (false ),
117- ex .getMessage (), CustomExceptionUtils .getAllStackTraces (ex ), CustomExceptionUtils .getAllCauses (ex ));
118- return new ResponseEntity <>(customErrorResponsePayload , HttpStatus .UNPROCESSABLE_ENTITY );
119- }
120- /* 2-2. In the case of @RequestParam: The error thrown when @RequestParam is completely missing in the Controller. */
121- @ ExceptionHandler (MissingServletRequestParameterException .class )
122- public ResponseEntity <?> missingServletRequestParameterException (MissingServletRequestParameterException ex , WebRequest request , HttpServletRequest h ) {
123-
124- CustomErrorResponsePayload customErrorResponsePayload = new CustomErrorResponsePayload (ex .getMessage (), request .getDescription (false ),
125- "Required parameter (" + ex .getParameterName () + ") is missing." , CustomExceptionUtils .getAllStackTraces (ex ), CustomExceptionUtils .getAllCauses (ex ));
126- return new ResponseEntity <>(customErrorResponsePayload , HttpStatus .UNPROCESSABLE_ENTITY );
127- }
128-
129- /* 3. Other Custom Validation: For example, search in the source with @ValidPart. */
130- @ ExceptionHandler (BindException .class )
131- public ResponseEntity <?> bindExceptionHandler (BindException ex , WebRequest request ) {
132-
133- Map <String , String > errorMessages = new HashMap <>();
134-
135- for (FieldError fieldError : ex .getBindingResult ().getFieldErrors ()) {
136- errorMessages .put (fieldError .getField (), fieldError .getDefaultMessage ());
137- }
138-
139- CustomErrorResponsePayload customErrorResponsePayload = new CustomErrorResponsePayload (ex .getMessage (), request .getDescription (false ), null ,
140- errorMessages ,
141- CustomExceptionUtils .getAllStackTraces (ex ), CustomExceptionUtils .getAllCauses (ex ));
142- return new ResponseEntity <>(customErrorResponsePayload , HttpStatus .UNPROCESSABLE_ENTITY );
143- }
144-
145-
146- // 4. Custom Validation using DB(select)
147-
148- @ ExceptionHandler (AlreadyExistsException .class )
149- public ResponseEntity <?> alreadyExistsException (AlreadyExistsException ex , WebRequest request ) {
150-
151- CustomErrorResponsePayload customErrorResponsePayload = new CustomErrorResponsePayload (ex .getMessage (), request .getDescription (false ),
152- ex .getMessage (), CustomExceptionUtils .getAllStackTraces (ex ), CustomExceptionUtils .getAllCauses (ex ));
153- return new ResponseEntity <>(customErrorResponsePayload , HttpStatus .UNPROCESSABLE_ENTITY );
154- }
155-
156- @ ExceptionHandler (IllegalStateException .class )
157- public ResponseEntity <?> illegalStateException (IllegalStateException ex , WebRequest request ) {
158-
159- CustomErrorResponsePayload customErrorResponsePayload = new CustomErrorResponsePayload (ex .getMessage (), request .getDescription (false ),
160- ex .getMessage (), CustomExceptionUtils .getAllStackTraces (ex ), CustomExceptionUtils .getAllCauses (ex ));
161- return new ResponseEntity <>(customErrorResponsePayload , HttpStatus .BAD_REQUEST );
162- }
163-
164-
165- @ ExceptionHandler (AlreadyInProgressException .class )
166- public ResponseEntity <?> alreadyInProgressException (AlreadyInProgressException ex , WebRequest request ) {
167-
168- CustomErrorResponsePayload customErrorResponsePayload = new CustomErrorResponsePayload (ex .getMessage (), request .getDescription (false ),
169- ex .getMessage (), CustomExceptionUtils .getAllStackTraces (ex ), CustomExceptionUtils .getAllCauses (ex ));
170- return new ResponseEntity <>(customErrorResponsePayload , HttpStatus .UNPROCESSABLE_ENTITY );
171- }
172-
173-
174- // config/resttemplate
175- @ ExceptionHandler (ResourceAccessException .class )
176- public ResponseEntity <?> restTemplateAccessException (ResourceAccessException ex , WebRequest request ) {
177-
178- CustomErrorResponsePayload customErrorResponsePayload = new CustomErrorResponsePayload (ex .getMessage (), request .getDescription (false ),
179- "We apologize for the inconvenience. The call to the 3rd Party API provider has failed. If the problem persists, please contact customer service." , CustomExceptionUtils .getAllStackTraces (ex ), CustomExceptionUtils .getAllCauses (ex ));
180- return new ResponseEntity <>(customErrorResponsePayload , HttpStatus .REQUEST_TIMEOUT );
181- }
182-
18359
18460 // Unhandled
18561 @ ExceptionHandler (Exception .class )
@@ -189,6 +65,4 @@ public ResponseEntity<?> unhandledExceptionHandler(Exception ex, WebRequest requ
18965 return new ResponseEntity <>(customErrorResponsePayload , HttpStatus .INTERNAL_SERVER_ERROR );
19066 }
19167
192-
193-
19468}
0 commit comments