Reputation: 532
I have a Jersey (2.14) application, which works all right. I have some services running there. Now I'd like to configure the ServletContainer so, that any not catched Exceptions should be intercepted and logged or emailed somewhere.
I have already an implementation of ApplicationEventListener and a test endpoint for generating an exception.
This is the method, which should generate an exception (this is working :-) :
@GET
@Path(TEST_EXCEPTION)
public String testException(@Context final ServletContext context) {
String s = null;
int size = 0;
if (System.nanoTime() % 10 != 0) {
s = null;
} else {
s = "No exception will occur";
}
size = s.length();
return Integer.toString(size) + ":" + s;
}
And this is the implementation if my ApplicationEventListener:
public class MyApplicationEventListener implements ApplicationEventListener {
private transient volatile int count = 0;
private int exceptions = 0;
@Override
public void onEvent(final ApplicationEvent applicationEvent) {
ApplicationEvent.Type type = applicationEvent.getType();
}
@Override
public RequestEventListener onRequest(final RequestEvent requestEvent) {
RequestEvent.Type type = requestEvent.getType();
if (type == RequestEvent.Type.ON_EXCEPTION) {
exceptions++;
}
count++;
return null;
}
}
And this the configuration in my web.xml:
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com....rest</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
com....filter.MyApplicationEventListener
</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.tracing</param-name>
<param-value>ALL</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
onEvent() and onRequest() are both been called, but when an Exception happens, I don't get a ON_EXCEPTION, but a START.
What am I doing wrong? Or how can I get all exceptions resulting from the methods of my Jersey service?
I'd like to have/make something like Spring's HandlerExceptionResolver.
Upvotes: 0
Views: 1379
Reputation: 9999
...when an Exception happens, I don't get a ON_EXCEPTION, but a START.
What am I doing wrong?
You need to return an instance of RequestEventListener from the START event, rather than returning null, in order to tell Jersey to carry on firing events for the request.
From 21.1.2. Event Listeners :
The second method onRequest is invoked by Jersey runtime every time a new request is received. The request event type passed to the method is always START. If you want to listen to any other request lifecycle events for the new request, you are expected to return an instance of RequestEventListener that will handle the request.
See https://stackoverflow.com/a/33271754/5473824 for an example which logs exception events.
Upvotes: 0
Reputation: 7255
You can do this pretty easy with an ExceptionMapper. If an exception occurs you still should send a response back to the client. But in here you could also send an email message or log a ticket etc.
Here is an example that I did for ConstraintViolations but this can be an exception mapper for type Exception. You can check the type of the exception and do something accordingly. In the toResponse you could implement a notfiyEmail method that could send the stack trace and messge to an email address for example or log a jira ticket which I have done in the past. Note though that you need to add the @Provider at the top and tell your rest Application/ResourceConfig to scan the package for this class. Alternatively you can register it manually with your ResourceConfig.
@Provider
public class ConstraintViolationExceptionMapper implements ExceptionMapper<ConstraintViolationException> {
private static final Logger logger = Logger.getLogger(ConstraintViolationExceptionMapper.class.getName());
public Response toResponse(ConstraintViolationException exception) {
final int violationCount = exception.getConstraintViolations().size();
ConstraintViolation<?>[] constraintViolations = exception.getConstraintViolations().toArray(
new ConstraintViolation<?>[violationCount]);
Violation[] violations = new Violation[exception.getConstraintViolations().size()];
for (int i = 0; i < violationCount; i++) {
ConstraintViolation<?> cv = constraintViolations[i];
Violation violation = new Violation(cv.getPropertyPath().toString(), cv.getMessage());
violations[i] = violation;
}
ConstraintErrorResponse responseEntity = new ConstraintErrorResponse();
responseEntity.setViolations(violations);
logger.info("Seinding exception response");
return Response.status(Response.Status.BAD_REQUEST).entity(responseEntity).build();
}
}
Upvotes: 3