In order to debug failing requests I would like to print all information coming from HttpServletRequest.
Now, it's possible that a request will partially fail (for ex. Several matches are successful, yet one has failed) in which case I would like to catch the exception in the internal method that failed, print the error + the ServletUtil.toStringHttpServletRequest() and continue providing service (degraded but still useful vs. complete request failure).
Our current implementation either catches the exception and prints dumb info ("getRules failed") or throws the exception all the way to doGet() (effectively canceling service for the user) where as in doGet() I have access to HttpServletRequest where I can print at the relevant debug info (headers, parameters...).
Passing HttpServletRequest to every function called during the request that might fail seems a bit ugly, I will do it if no other elegant solution will pop up.
Making a before head ServletUtil.toStringHttpServletRequest() and storing it in a ThreadLocal map would be wasteful both in memory and CPU time. For some reason it feels wrong to store the HttpServletRequest object in ThreadLocal (please correct if I'm wrong).
Debug information is written both to local machine log and is emailed directly to devs (Great work log4j TLSSMTPAppender), so logging in several places won't be practical (Will need to assemble several emails to understand what's going on) and ssh'ing into the server is old age :) (We're all cloudy here... server might not exist by the time I get to look at the error)
So, my solution is gaining access to a "PrintErrorUtility" (TODO: better name it). That will receive (String errorMsg, Throwable t, HttpServletRequest) which will print the error together will all the relevant info... This will be called from internal try {} catch blocks that will notify about the error but will not cancel the request because of it.
Obviously I'm taking about servers running in production.
Comments? Please advise.
Thank you, Maxim.
Do this task in a Filter after the FilterChain#doFilter() call. The ServletRequest object is already there. In the business code where this exception is to be suppressed gracefully, store the exception as a request attribute and just let the Filter check/grab it from the request.
Update: as per the comments, here's an example:
public class Context {
private static ThreadLocal<Context> instance = new ThreadLocal<Context>();
private HttpServletRequest request;
private List<Exception> exceptions = new ArrayList<Exception>();
private Context(HttpServletRequest request) {
this.request = request;
this.request.setAttribute("exceptions", exceptions);
}
public static Context getCurrentInstance() {
return instance.get();
}
public static Context newInstance(HttpServletRequest request) {
Context context = new Context(request);
instance.set(context);
return context;
}
public void release() {
instance.remove();
}
public void addException(Exception exception) {
exceptions.add(exception);
}
}
And here's how to use it in your controller servlet:
Context context = Context.newInstance(request);
try {
executeBusinessCode();
} finally {
context.release();
}
And here's how you could use it in the executed business code:
} catch (Exception e) {
Context.getCurrentInstance().addException(e);
}
Related
Lets say we have a rest service defined as:
#GET
#Produces("application/json")
public Response getAllCategories(#QueryParam(value="startIndex") int startIndex, #QueryParam(value="size") int size)
{
logger.info("[SampleCategoryController][getAllCategories]");
List<YpCategory> categoryList = sampleCategoryService.getAllCategories(startIndex, size);
return Response.ok(categoryList).build();
}
and the service is defined as:
public class SampleCategoriesServiceImpl {
public List<YpCategory> getAllCategories(int startIndex, int size) {
...
//call some method that throws a runtime exception
...
}
}
And an Application Exception handler:
#Provider
#Component
public class ApplicationExceptionHandler implements ExceptionMapper<Throwable> {
#Override
public Response toResponse(Throwable ex) {
String internalError = "There was a problem processing your request.";
return Response.serverError().entity(new ExceptionResponse(500, internalError)).build();
}
}
}
Exception response object: Let the exception bubble up to the ApplicationExceptionHandler and return the ExceptionResponse Object. This way seems cleaner because the service doesn't have to try to handle an exception that it can't really do anything with and the client will still receive a json response.
Response wrapper: The category object would extend some type of generic response wrapper object with information about error codes then I would always have to wrap the method that can throw a runtime exception in a try/catch block and set the error codes and message info in the catch block.
Is one of these ways preferred? Are there cons to using either one of these methods to handle errors?
I think you should use the ExceptionMapper in this case. It is cleaner to let exceptions be handled outside of your implementation.
Also your implementation should be as less possible aware of HTTP. The less your implementation knows about the other parts of your framework the more flexible it will become.
To give an example. Lets say that in the future there is support for a non-HTTP protocol and error messaging will go different then using HTTP status code. You can do the implementation at the level of ExceptionMapper without changing your implementation. Otherwise you have to refactor your application to be aware of the non-HTTP protocol.
Just to be clear, I don't say there is an other implementation available now. It is just a theory.
I am working on a solution that should do something if i am in the middle of a web request or something else if not.
What i am doing is
#Autowired private HttpServletRequest request;
And then trying to access a variable:
request.getRequestURI()
But i am getting java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request...
I would like to avoid the exception and somehow ask the HttpServletRequest weather or not i am in a web request or not.
Is there any way to do it?
Example:
Additional info:
#Override
public void trace(String msg) {
if (loggerFactory.isRegisteredUrl(request.getRequestURI())){
loggerFactory.getCustomeLogger(request.getRequestURI()).trace(msg);
return;
}
nativelogger.trace(msg);
}
You should probably (not tested) use RequestContextHolder.getRequestAttributes():
Return the RequestAttributes currently bound to the thread.
Returns:
the RequestAttributes currently bound to the thread, or null if none bound
So, if the method returns null, the current thread is not handling a request. If it returns a non-null value, it is handling one.
I'm trying to pass error information back from an error on a Spring Webflow 2 page through an AbstractFlowHandler. The relevant code looks like this:
#Override
public String handleException(FlowException e, HttpServletRequest request, HttpServletResponse response) {
if (e instanceof NoSuchFlowExecutionException) {
return DEFAULT_URL;
} else {
logger.warn(String.format("Flow threw exception %1$s", e.getMessage()), e);
return ERROR_URL;
}
}
EDIT: The "normal" result of simply returning back to the calling routine at this point is always a 302 REDIRECT, so the "request" and "response" objects attached to this call are lost, and fresh objects are created when the redirect is executed. LeandreM's comment below (using forward()) gives a workaround, but it would be nice if there was some way around that redirect INSIDE the normal processing path. However, I have not been able to find one.
What I would like to do is pass the exception object "e" along to the error page, so that I can print some information about it. But I can't figure out the "proper" way to do this - do I attach it to the request object, the response object, or do it some other way?
Here is a little background of my problem:
I'm using Spring MVC 3.1.2.RELEASE. The server is deployed on Amazon AWS. I have a simple controller.
public class MyWebController implements Controller {
#Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
try {
String delegateGuid = request.getParameter("delegateGuid");
String serviceCodesToBeUpdated = request.getParameter("serviceCodesToBeUpdated");
if (StringUtils.isBlank(delegateGuid) || StringUtils.isBlank(serviceCodesToBeUpdated)) {
throw new MyException("delegateGuid and/or serviceCodesToBeUpdted cannot be null or empty");
}
...
I have a client script that makes POST request to this endpoint. But sometimes, I hit this MyException that tells me the params are not set. But client logs show that the params are set correctly before sending the requests. The difficult part of debugging this is that it is not reproducible.
Does anyone know what could possibly have caused this issue? I know this might not be the level of detail enough to identify the problem. But if you can suggest any debug logs I could insert into my code, that would be helpful as well. I'm lost in that I don't even know where to start debugging this.
Thanks.
Java Code:
#GET
#Path("/stop/{id}")
public void stop(
#PathParam("id") String id,
#Context HttpServletRequest request,
#Context HttpServletResponse response) throws ServletException,
IOException
{
server.stop(id);
}
Java Warning's being thrown to console:
WARNING: A HTTP GET method, public void com.myPackage.stop(java.lang.String,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws javax.servlet.ServletException,java.io.IOException, MUST return a non-void type.
You really shouldn't be using a GET operation.
I would use a POST operation and return a 201 Created with a link to a resource which describes the new state of the system.
For example, I would redirect to a shutdown status resource:
POST /stop/123
...
201 CREATED
Location:
http://acme.com/shutdownstatus/123
The the client can poll the resource to check on the status
GET /shutdownstatus/123
...
<shutdown xmlns="http://schemas.serverapp.com/shutdown">
<status>pending</status>
<message>Looks good so far</message>
</shutdown>
This new GET operation will always return the state of the server for that id. That way you know if it was shutdown correctly or not. If server shutdown takes a long time, the client could poll that resource to check on different shutdown statuses until it is complete. This way you can return from the original server shutdown request quickly.
If an exception was thrown in your process, I wouldn't return it to the client, I would have a status for the exception in the server status resource. I always avoid making a client handle an exceptional case when I can represent it as a resource. This allows you to change the resource freely, such as when the exception causing method is changed or fixed, without changing the external API.
The warning is correct. A GET operation should be idempotent, so shouldn't affect server state. If you're not returning anything, the method can't be doing anything useful. You should change it to POST or some other appropriate HTTP operation.
url must be as follows.
{servername}:{port}/{applicationname}/{standardname}/{your service name}/{your operation name}
ex: http://localhost:8080/restful/jersy/user/service/getUserDets
restful - applicationname
jersy - standardname {optional}
user/service - service name
getuserdets - operation name
Try to define it as *V*oid and return null.
#GET
#Path("/stop/{id}")
public void stop(
#PathParam("id") String id,
#Context HttpServletRequest request,
#Context HttpServletResponse response) throws ServletException,
IOException
{
server.stop(id);
return null;
}