-
Notifications
You must be signed in to change notification settings - Fork 209
/
ExceptionHandlingController.java
248 lines (222 loc) · 7.77 KB
/
ExceptionHandlingController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
package demo1.web;
import java.sql.SQLException;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;
import demo.exceptions.DatabaseException;
import demo.exceptions.InvalidCreditCardException;
import demo.exceptions.OrderNotFoundException;
import demo.exceptions.SupportInfoException;
import demo.exceptions.UnhandledException;
/**
* A controller whose request-handler methods deliberately throw exceptions to
* demonstrate the points discussed in the Blog.
* <p>
* Contains its own <tt>@ExceptionHandler</tt> methods to handle (most of) the
* exceptions it raises.
*
* @author Paul Chapman
*/
@Controller
@RequestMapping("/local")
public class ExceptionHandlingController {
protected Logger logger;
public ExceptionHandlingController() {
logger = LoggerFactory.getLogger(getClass());
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* . . . . . . . . . . . . . . REQUEST HANDLERS . . . . . . . . . . . . .. */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/**
* Home page.
*
* @return The view name (an HTML page with Thymeleaf markup).
*/
@GetMapping("")
String home1() {
logger.info("Local home page 1");
return "local";
}
/**
* Home page.
*
* @return The view name (an HTML page with Thymeleaf markup).
*/
@GetMapping("/")
String home2() {
logger.info("Local home page 2");
return "local";
}
/**
* No handler is needed for this exception since it is annotated with
* <tt>@ResponseStatus</tt>.
*
* @return Nothing - it always throws the exception.
* @throws OrderNotFoundException
* Always thrown.
*/
@GetMapping("/orderNotFound")
String throwOrderNotFoundException() {
logger.info("Throw OrderNotFoundException for unknown order 12345");
throw new OrderNotFoundException("12345");
}
/**
* Throws an unannotated <tt>DataIntegrityViolationException</tt>. Must be
* caught by an exception handler.
*
* @return Nothing - it always throws the exception.
* @throws DataIntegrityViolationException
* Always thrown.
*/
@GetMapping("/dataIntegrityViolation")
String throwDataIntegrityViolationException() throws SQLException {
logger.info("Throw DataIntegrityViolationException");
throw new DataIntegrityViolationException("Duplicate id");
}
/**
* Simulates a database exception by always throwing <tt>SQLException</tt>.
* Must be caught by an exception handler.
*
* @return Nothing - it always throws the exception.
* @throws SQLException
* Always thrown.
*/
@GetMapping("/databaseError1")
String throwDatabaseException1() throws SQLException {
logger.info("Throw SQLException");
throw new SQLException();
}
/**
* Simulates a database exception by always throwing
* <tt>DataAccessException</tt>. Must be caught by an exception handler.
*
* @return Nothing - it always throws the exception.
* @throws DataAccessException
* Always thrown.
*/
@GetMapping("/databaseError2")
String throwDatabaseException2() throws DataAccessException {
logger.info("Throw DataAccessException");
throw new DataAccessException("Error accessing database");
}
/**
* Simulates an illegal credit-card exception by always throwing
* <tt>InvalidCreditCardException</tt>. Handled by
* <tt>SimpleMappingExceptionResolver</tt>.
*
* @return Nothing - it always throws the exception.
* @throws InvalidCreditCardException
* Always thrown.
*/
@GetMapping("/invalidCreditCard")
String throwInvalidCreditCard() throws Exception {
logger.info("Throw InvalidCreditCardException");
throw new InvalidCreditCardException("1234123412341234");
}
/**
* Simulates a database exception by always throwing
* <tt>DatabaseException</tt>. Handled by
* <tt>SimpleMappingExceptionResolver</tt>.
*
* @return Nothing - it always throws the exception.
* @throws DatabaseException
* Always thrown.
*/
@GetMapping("/databaseException")
String throwDatabaseException() throws Exception {
logger.info("Throw InvalidCreditCardException");
throw new DatabaseException("Database not found: info.db");
}
/**
* Always throws a <tt>SupportInfoException</tt>. Must be caught by an
* exception handler.
*
* @return Nothing - it always throws the exception.
* @throws SupportInfoException
* Always thrown.
*/
@GetMapping("/supportInfoException")
String throwCustomException() throws Exception {
logger.info("Throw SupportInfoException");
throw new SupportInfoException("Custom exception occurred");
}
/**
* Simulates a database exception by always throwing
* <tt>UnhandledException</tt>. Must be caught by an exception handler.
*
* @return Nothing - it always throws the exception.
* @throws UnhandledException
* Always thrown.
*/
@GetMapping("/unhandledException")
String throwUnhandledException() throws Exception {
logger.info("Throw UnhandledException");
throw new UnhandledException("Some exception occurred");
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* . . . . . . . . . . . . . EXCEPTION HANDLERS . . . . . . . . . . . . .. */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/**
* Convert a predefined exception to an HTTP Status code
*/
@ResponseStatus(value = HttpStatus.CONFLICT, reason = "Data integrity violation")
// 409
@ExceptionHandler(DataIntegrityViolationException.class)
public void conflict() {
logger.error("Request raised a DataIntegrityViolationException");
// Nothing to do
}
/**
* Convert a predefined exception to an HTTP Status code and specify the
* name of a specific view that will be used to display the error.
*
* @return Exception view.
*/
@ExceptionHandler({ SQLException.class, DataAccessException.class })
public String databaseError(Exception exception) {
// Nothing to do. Return value 'databaseError' used as logical view name
// of an error page, passed to view-resolver(s) in usual way.
logger.error("Request raised " + exception.getClass().getSimpleName());
return "databaseError";
}
/**
* Demonstrates how to take total control - setup a model, add useful
* information and return the "support" view name. This method explicitly
* creates and returns
*
* @param req
* Current HTTP request.
* @param exception
* The exception thrown - always {@link SupportInfoException}.
* @return The model and view used by the DispatcherServlet to generate
* output.
* @throws Exception
*/
@ExceptionHandler(SupportInfoException.class)
public ModelAndView handleError(HttpServletRequest req, Exception exception)
throws Exception {
// Rethrow annotated exceptions or they will be processed here instead.
if (AnnotationUtils.findAnnotation(exception.getClass(),
ResponseStatus.class) != null)
throw exception;
logger.error("Request: " + req.getRequestURI() + " raised " + exception);
ModelAndView mav = new ModelAndView();
mav.addObject("exception", exception);
mav.addObject("url", req.getRequestURL());
mav.addObject("timestamp", new Date().toString());
mav.addObject("status", 500);
mav.setViewName("support");
return mav;
}
}