I'd like my Restlet application to log the stack trace for any Resource that generates a 500-series HTTP error (using the Context's Logger). As far as I can tell, this is not the default behavior.
In other words, I don't want my Resource classes to have any logger code at all in the represent and acceptRepresentation methods - they just throw a ResourceException. I want the logging logic to be handled in a centralized way across all Resource instances.
I can think of a couple of hackish ways of doing this (e.g., inherit from a Resource subclass that handles the logging logic), but it just seems like this is something that should be built-in to the framework.
What am I missing?
Take a look at StatusService:
Service to handle error statuses. If an exception is thrown within your application or Restlet code, it will be intercepted by this service if it is enabled. When an exception or an error is caught, the getStatus(Throwable, Request, Response) method is first invoked to obtain the status that you want to set on the response. [...]
I just discovered this last month and it allowed me to really compress a lot of my error handling code and also to ensure that exceptions were being handled, and being handled uniformly.
You might be able to use a filter to do this; in afterHandle() it could check the status code, and then try to log the exception. I'm not sure whether the exceptions are available to the filters though.
Related
I am new to Axon framework and am trying to implement an application using CQRS with state-stored aggregates. The application relies on a database constraint (using H2 for now) to enforce uniqueness on a name attribute. I would like to catch this exception and rethrow it as a user-friendly domain exception.
Per the Axon documentation:
Exception Handling says "an #ExceptionHandler will only handle exceptions thrown from message handling functions in the same class"
Message Intercepting documentation says "A function annotated with #ExceptionHandler will be regarded as a handler interceptor which will only be invoked for exceptional results. Using annotated functions to this end for example allow you to throw a more domain specific exception as a result of a thrown database/service exception."
But I cannot get this to work. I have tried adding exception handlers as follows:
#ExceptionHandler
public void handle(ConstraintViolationException ex) throws Exception {
if (ex.getMessage().contains("UNQ_COMPANY_ID") || ex.getMessage().contains("UNQ_PLAN_NAME")) {
throw new DomainException("Plan name and company id must be unique");
}
throw ex;
}
but this method is not called. I have tried putting the exception handler method on the aggregate and on a separate command handler class, tried adding resultType=ConstraintViolationException.class, and tried catching other types of exceptions including Exception, RuntimeException, AxonServerRemoteCommandHandlingException, etc. but this method is never called.
I can see the error in the log output:
org.axonframework.axonserver.connector.command.AxonServerRemoteCommandHandlingException: An exception was thrown by the remote message handling component: org.hibernate.exception.ConstraintViolationException: could not execute statement
Is it possible to catch database exceptions in state-stored aggregates? If it is, can someone point me towards what I am doing wrong?
The statement "an #ExceptionHandler will only handle exceptions thrown from message handling functions in the same class" makes me wonder whether I need to create a custom repository class (rather than using the default GenericJpaRepository) but that seems like a lot more work than should be necessary.
Thank you!
Update: I was able to roughly accomplish what I want by adding a UnitOfWork parameter to the #CommandHandler method and using it to registering a rollback callback on it as follows:
uow.onRollback(unit -> {
DefaultUnitOfWork duow = (DefaultUnitOfWork) unit;
Throwable ex = duow.getExecutionResult().getExceptionResult();
while (ex != null) {
if (ex.getMessage().contains("UNQ_PLAN_NAME")) {
throw new RuntimeException("Plan name must be unique");
}
ex = ex.getCause();
}
});
But this seems kind of verbose, as well as limiting me to throwing unchecked exceptions only. This also doesn't feel like the right way to do this though because I assume the purpose of the #ExceptionHandler annotation is to eliminate need for code like the above.
This is doable of course.
Actually, the best pointer I could give you if the code-samples repo where you can see a sample about distributed exceptions.
In general, as you could see in your shared log, the 'original' exception is wrapped into an AxonServerRemoteCommandHandlingException meaning you will have to handle that. Doing that, you can pretty much add anything to the details field of this class, adding the indication you had a ConstraintViolationException for example (or an ERROR_CODE, like HTTP protocol does) and you are fine to unwrap it on the other side.
What might be the "gotcha" you require, is to know that an #ExceptionHandler annotated method should reside in the object handling the message. So if you want to react to a failing command handling operation (which would be the case in your sample), you will need to place the exception handler in the Aggregate, next to the Command Handler.
That fact you get an AxonServerRemoteCommandHandlingException to me suggests the exception is caught on the command dispatching end. So, prior to dispatching a command on the CommandGateway/CommandBus.
However, whether this is the problem at hand, isn't clear to me right now, since the sample only shows the exception handler and not where it resides. Please share whether my assumption on the placement of the exception handler is correct. If not, we'll dive into this deeper to get to the cause.
Is it fine to throw an exception on the server side when the requested resource was not found?
the client receives a 404 not found. My concern is whether it is fine/wrong to throw an exception on the server side when this happens.
It's hard to assume what your are trying to do with the level of details you added to your question.
However, if you handle the exceptions properly, there may be nothing wrong with that approach. Have a look at the approaches used by some frameworks:
JAX-RS
You can throw a WebApplicationException, that will be mapped a response. You can define your own subclasses of WebApplicationException or use the existing ones. The NotFoundException, for example, will be mapped to a response with the 404 status code. For more details on the existing exceptions, refer to this answer.
You also can create your own ExceptionMapper to map any exception to a desired response.
Spring MVC
You can map exceptions to responses by annotating an exception class with #ResponseStatus.
It also gives you the possibility to implement a HandlerExceptionResolver or extend one of the existing implementations, such as the AbstractHandlerExceptionResolver.
Another approach would be using a ResponseEntityExceptionHandler annotated with #ControllerAdvice and define the handled exceptions by annotating the implemented method with #ExceptionHandler
Basically it is not ideal to throw reserved status codes of exception. You should handle this exceptions internally and prepare your own code with meaning full message that client should know the actual problem.
I would say add a filter to capture 404 and add custom information about the 404 details.
In case of pure REST implementation, any resource-id missing and malformed URL will return 404.
As far as REST contract, both cases are correct to have 404 response. But more details on what type of resource is missing will help the client side consuming it to take appropriate actions.
Related discussion:
return-404-when-a-rest-resource-is-not-found
From perspective of semantics: Exception should be thrown if condition is such that condition is unrecoverable and devs must be notified about it.
Server cannot resolve auth request in the beginning of a session - this is serious enough situation and exception is appropriate.
User didn't fill out obligatory field and tried sending a form. This problem can be fixed and an exception would be a bad design.
I have something like the following in a Spring project:
#RequestMapping(value = "/someRestUrl", method = RequestMethod.POST)
public SomeSo doSomeWork(#Validated #RequestBody SomeSo someSo) {
...
}
I recently changed SomeSo to have an additional parameter that was required:
#NotNull
private String someParameterThatNeedsToBeProvided;
Then I promptly left for the evening and when I got back to work the next day, my requests that were working before I made this change were no longer working. It took me forever to figure out why because I can't remember what I did less than 24 hours ago and, more importantly, because the error message sent to the client was only the following with no further details:
How can I get more information on what the issue is by either logging or sending this information back to the client? Is there some configuration I can do to get either more detailed logging for errors like this (I'd like to NOT include all of Spring's logging at DEBUG level, though) or provide this information to the client?
Note: I'd like to clarify that the request was parseable but was just missing the new parameter. It wasn't poorly formatted JSON.
You would want to check out the Errors class or the BindingResult class. Those give you details on what problems occurred due to #Validated. You can include them in the method parameters to interact with them. They are also available to templates. You would want to make a custom error page to output the details of the errors if that is something you want to expose.
I have faced this same error, and it was due to the incoming JSON not matching the object it is being mapped to.
Most probable cause is an empty collection, a single item mapped to a collection or some incorrect data type conversion.
You should enable DEBUG for Spring to detect the failure. Usually this errors are caused by inner exceptions from Jackson Mapper... So take a look at the log to find it, and you'll get an idea of what is the cause for your particular error.
So, I have a camel context that has a DeadLetterChannel with no redeliveries at the context level. Within the context I have a route:
from("direct:input")
.routeId("enrichHeader")
.setHeader("myHeader").constant("someValue)
.to("direct:output");
I have a unit test in which I interceptSendToEndpoint("direct:output") and cause an exception to be thrown.
Then in the unit test I do producerTemplate.sendBody(theBody).
Now, as configured above on exception the message gets sent to the dead letter channel. All's well. However, if I configure a loggingErrorHandler I get odd behavior. So if I update the above route as follows:
from("direct:input")
.routeId("enrichHeader")
.errorHandler(
loggingErrorHandler("com.myco.myproject")
.level(LoggingLevel.WARN))
.setHeader("myHeader").constant("someValue)
.to("direct:output");
When I run the test now I get two unexpected behaviors. First, the exception is still logged at level ERROR instead of the configured WARN. Second, the exception is propagated back to the producerTemplate.sendBody(theBody) invokation.
On the one hand, the logging at ERROR is obviously odd. The other part that seems odd is that the handler is propagating the exception. I would have thought it would have marked it as handled and be done with it.
Is this expected behavior? Seems like documentation for the LoggingErrorHandler is lacking.
LoggingErrorHandler do nothing more than logging the exception.
if you want to skip the exception you have to define a policy as followed
onException(com.myco.myproject.MyException.class).continued(true);
or you have to use a doTry()..doCatch() just like try{...} catch{...} block in java.
for example:
from("direct:input").routeId("enrichHeader")
.doTry()
.setHeader("myHeader").constant("someValue)
.to("direct:output")
.doCatch(MyException.class)
.process(new MYExceptionLoggerAndHandler())
.end();
First, I am throwing run time exceptions for all unrecoverable exceptions, this causes these exceptions to travel up to the container, where I currently use an error page (defined in web.xml). In this error page is a scriptlet that invokes the logger.
The issue I am having with this is that the exception is no longer on the stack at this invocation. I have access to it from a request scope variable ("javax.servlet.error.message"). This string is the stack trace. I need this stack trace for logging purposes obviously, and on different app servers "javax.error_message" can be turned off for security reasons.......
So my question is, how can best log runtime exceptions from within Java EE apps without wrapping everything in this:
try {} catch (Exception e) {logger.log(...)}
?
I want some way to invoke the logger from the container maybe... right before the container catches the exception for example.
I found a solution. By adding a response filter and wrapping chain.doFilter(req, resp) like so:
try {
chain.doFilter(req,resp);
} catch (Exception e) {
logger.error("", e);
throw new RuntimeException(e);
}
This works fine so far and isn't dependent on a particular framework or app server.
There is nothing I know of in Servlet API to accomplish this.
However, you can do this in Tomcat with an instance listener. You can install a listener in context.xml like this,
<InstanceListener>myapp.MyListener</InstanceListener>
Tomcat fires InstanceEvent.AFTER_SERVICE_EVENT event right after the container catches the exception and before it throws the exception again. You can invoke the logger right there.
Correct me if I'm wrong, but the 'exception' object is present as a variable.. called 'exception' in your 'error' jsp. You could always use this object to log retrieve the exception information and log in in the error jsp itself.
AOP (Aspect Oriented Programming) would be my first choice.
You define:
join point (a runtime exception is thrown).
advice (your code to log the exception).
point cuts (which parts of your applications are "listening" this aspect).
Take a look at http://www.aspectj.org/