Enforce QoS metrics on Java methods via timeouts in Jersey server - java

In perfect world, I would imagine that there is an annotation like #QoS(10, CONSTANT_RETURN_OBJECT) which can be placed around java methods and if they take longer than the specified time (10 seconds in this example) to execute then the method execution is essentially considered timed out and we return a pre-packaged CONSTANT_RETURN_OBJECT defined by the developer to indicate empty results.
But realistically, what is a good approach supported by or recommended for enforcing how long a jersey-server method can run for before we say its too darn long and just return and go on our merry way?
And its a given (for my question here) that you have no control over the client side that is calling jersey-server so you can NOT go set a timeout there ... which is why you are enforcing some reasonable ones on the server side.
UPDATE:
I guess what I am asking to some degree is if there is an annotation that would essentially wrap a method call as an Executor driven task and run it with a timeout? Sort of like what the code written in the answers for these two posts does:
How to set a timer in java
How do I call some blocking method with a timeout in Java?

The way to do this would be to implement a servlet filter. A basic filter looks like this:
public class TimeoutFilter implements Filter {
#Override
public void doFilter(final ServletRequest servletRequest,
final ServletResponse servletResponse,
final FilterChain chain) throws IOException, ServletException {
final HttpServletRequest req = (HttpServletRequest)servletRequest;
try {
// Execute this with a time limit
chain.doFilter(servletRequest, servletResponse);
}
catch (Exception e) {
// Handle exceptions here; you should state the exceptions explicitly
// rather than just catching Exception
}
}
}
You can then set up an Executor or whatever in the filter to provide a time limit for the request.

Related

How can I check if servlet request is internal with Jetty?

We have a embedded Jetty 10.0.12 server, configure everything programmably (no web.xml) and already have a few servlets registered. We want to add a new servlet for an internal API. I have already done this. We now want to secure it. Security would be pretty simple: if the request did not come from within the server, reject it. This is good enough because we employ other security standards in the other servlets. I know where to start: create and register a filter:
public class InternalFilter implements Filter {
#Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
// TODO: Check if request is internal.
// I.e., came from another registered servlet in the same JVM.
// If it is internal, then `chain.doFilter`.
}
}
I do not know how to proceed from here.
I'll start by assuming that "internal" means you are using either RequestDispatcher.include() or RequestDispatcher.forward().
If so, then you can check the HttpServletRequest.getDispatcherType() value.
Value
Meaning
DispatcherType.FORWARD
Request arrived from a call to RequestDispatcher.forward().
DispatcherType.INCLUDE
Request arrived from a call to RequestDispatcher.include().
DispatcherType.REQUEST
Request arrived from the beginning of the server handling tree.
DispatcherType.ASYNC
Request arrived from call to HttpServletRequest.startAsync()
DispatcherType.ERROR
Request arrived from error handling (either an unhandled exception, or from a call to HttpServletResponse.sendError()

How to save requests and responses to database in spring boot

I would like to write an aspect or something like that and whenever a request comes to the controller it saves the request and the response to the database.
First question is what type I should use in my entity for request and response ( string, blob, etc)
Second question, how to get request,response and its controller name to create the entity to save to database ?
Lastly, is it possible to calculate response time (time spent in the controller) of the controller ?
First question is what type I should use in my entity for request and
response ( string, blob, etc)
It mainly depends on the database vendor and request/response length.
String may be limited for some vendors and blob is so required.
On the other hand, matching on blob is slower.
Another alternative is using a nosql format such as JSON.
Second question, how to get request,response and its controller name
to create the entity to save to database ?
There are really several ways.
You could take advantage of built-in Spring Boot http tracing features but it has a limitation : posted/received of request/responses are not available.
5.8. HTTP Tracing
HTTP Tracing can be enabled by providing a bean of type
HttpTraceRepository in your application’s configuration. For
convenience, Spring Boot offers an InMemoryHttpTraceRepository that
stores traces for the last 100 request-response exchanges, by default.
InMemoryHttpTraceRepository is limited compared to other tracing
solutions and we recommend using it only for development environments.
For production environments, use of a production-ready tracing or
observability solution, such as Zipkin or Spring Cloud Sleuth, is
recommended. Alternatively, create your own HttpTraceRepository that
meets your needs.
The httptrace endpoint can be used to obtain information about the
request-response exchanges that are stored in the HttpTraceRepository.
5.8.1. Custom HTTP tracing
To customize the items that are included in each trace, use the
management.trace.http.include configuration property. For advanced
customization, consider registering your own HttpExchangeTracer
implementation.
Alternatives are implementing a filter for requests/responses and log in it.
For example :
#Component
public class RequestResponseStoringFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
long start = System.currentTimeMillis();
try {
chain.doFilter(req, resp);
} finally {
// Measure elapsed time
long elapsed = System.currentTimeMillis() - start;
// store request data and store response data in a DB
.....
}
}
#Override
public void destroy() {}
#Override
public void init(FilterConfig arg0) throws ServletException {}
}
Lastly, is it possible to calculate response time (time spent in the
controller) of the controller ?
The way implement a Filter can do that as shown above.
The httptrace endpoint way provides that with the timeTaken field.
FIY, here is the content of a HttpTrace instance :
HttpTrace.Principal getPrincipal()
HttpTrace.Request getRequest()
HttpTrace.Response getResponse()
HttpTrace.Session getSession()
Instant getTimestamp()
Long getTimeTaken()
This kinda expands on the other answers, but I think It warrants a separate answer.
If your pulling in spring-boot-starter-web, then you're already pulling in spring-aop. If your going to go down the point cut route though, I'd highly recommend just using the Micrometer #Timed annotation which comes with spring-boot-starter-actuator. I've written my own metric pointcuts a many times, but if your just after timings and counts of successes and failures, #Timed works great.
I'd also highly recommend looking into using a time series database (e.g influx) for storing things like response times and other performance metrics. Keep your raw payloads and other possible auditing concerns in a separate DB. There are some very powerful things you can do with influx and running Grafana or Chronograf on top of it. Without a doubt one of the best things my current company has done is years is adopting Influx/Chronograf.
With regards to the request/response capture, I had a weird edge case in my work flow once where the http trace just wasn't working for some hard requirements. You can capture the contents directly in a chain filter yourself with a ContentCachingRequestWrapper
Then you can access them with:
#Component
class MyPayloadCapturingFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request)
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response)
filterChain.doFilter(requestWrapper, responseWrapper)
def requestBody = new String(requestWrapper.contentAsByteArray)
def responseBody = new String(responseWrapper.contentAsByteArray)
//..do something with them
}
}
note the OncePerRequestFilter, I found times when my Filter was firing multiple times for the same request. This prevents that.
Add this dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
then, create an Around aspect for your controllers' methods' execution:
#Around("within(path.to.your.controller.*)")
public Object pointcutWithin(ProceedingJoinPoint joinPoint) throws Throwable {
logger.info(" ###### pointcutWithin() before");
long start = System.nanoTime();
Object result = joinPoint.proceed();
logger.info(" ###### pointcutWithin() after");
long end = System.nanoTime();
long timeElapsedInMillis = (end - start) / 1000000;
logger.info(" ###### elapsed time in millis: "+timeElapsedInMillis);
return result;
}
As for persisting: first, get the req and resp like so:
MyRequest req = (MyRequest) joinPoint.getArgs()[0];
MyResponse resp = (MyResponse) result;
then it's up to you what you actually want t o persist. For classes with simple fields I'd go with a varchar, just remember to override their toString methods.

How do you stop spring swallowing exceptions?

When something fails on the server side because the database and the application are out of sync instead of getting an error and the application crashing spring/tomcat seems to swallow the exception and pretend nothing has happened.
Call me crazy but if the program fails catastrophically I want it to actually fail catastrophically! Is there anyway to switch this behaviour off? It's really slowing development down when the server pretends that everything is fine when it's just thrown up into the logs.
If this isn't the spring/tomcat default then what else might be causing it?
We are using a boatload of libraries and frameworks unfortunately. Spring would be the usual suspect but it could be something else.
Update
It's a sql server database which we are connecting to using SqlServerDataSource. Hibernate is in use in some parts of the project but is used to query the database at login time. On the client side we are using extjs and we are also using ExtDirectSpring to annotate methods for the client side to talk to. To translate the data going across the wire there's Jackson, which then gets wrapped by the extdirect json handler.
There's some AOP stuff going on thats to do with logging exceptions but deleting that code results in the same behaviour.
Further update
Ok its not a good idea to let your sever crash! See my answer below for my proposed middle ground.
If you really want to do that (but IMHO you should not ...) you can use a filter that will block the application once it let an uncaught exception go. It could be something like :
public class CrashFilter implements Filter {
private boolean crashed = false;
private String msg = "Major problem : application stopped";
#Override
public void doFilter(ServletRequest sr, ServletResponse sr1, FilterChain fc) throws IOException, ServletException {
if (crashed) {
HttpServletResponse resp = (HttpServletResponse) sr1;
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg);
return;
}
try {
fc.doFilter(sr, sr1);
}
catch (Exception ex) {
crashed = true;
throw new ServletException(ex);
}
}
// init and destroy omitted from brevity
}
Ok so I did this in the end. I've basically used the ideas above but thought there was enough extra to post my own answer.
It turns out you really shouldn't do this as other people suggested and I've added a bit at the bottom to say why!
Here's my filter:
public class FailOnErrorFilter implements Filter
{
#Override
public void init(FilterConfig config) throws ServletException
{
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException
{
try {
filterChain.doFilter(request, response);
}
catch (Exception exception) {
System.exit(1);
}
}
#Override
public void destroy()
{
}
}
To get this working you have to modify the web.xml:
<filter>
<filter-name>failingFilter</filter-name>
<filter-class>fullyQualified.FailOnErrorFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>failingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The top one defines the filter + the second one says use it everywhere.
ExtDirectSpring
After doing the above I realised that ExtDirectSpring was a further culprit. It's default behaviour is to swallow all exceptions in server side methods.
I was worried I was going to have to patch the library but thankfully someone else had already complained about this and it got fixed in 1.3.6. Initially I tried upgrading to the latest version but it broke a load of code! What a great library. Anyway 1.3.6 added in the ability to switch off the suppression of errors by doing the following:
//this is to switch off blanket switching of exceptions in extdirect spring
#Component
public class NoExceptionHandling implements RouterExceptionHandler
{
#Override
public Object handleException(MethodInfo methodInfo, BaseResponse baseResponse, Exception e, HttpServletRequest httpServletRequest)
{
throw new RuntimeException(e);
}
}
As the name suggests extdirectspring uses spring and so doesn't make its dependencies obvious to calling code, however if you go digging (its on github). You'll see in RouterController it calls the following method in the catch
private Object handleException(MethodInfo methodInfo, BaseResponse response, Exception e, HttpServletRequest request) {
return configurationService.getRouterExceptionHandler().handleException(methodInfo, response, e, request);
}
Where router controller does this:
#Autowired(required = false)
private RouterExceptionHandler routerExceptionHandler;
public RouterExceptionHandler getRouterExceptionHandler() {
return routerExceptionHandler;
}
It sets up a default one if you dont provide one.
Update - why you shouldn't do this
It turns out you really shouldn't call System.exit in a tomcat application. Not only does it bring down your application it also causes the server to exit. This brings down any other applications running aswell!
It's also not appropriate for a number of other reasons:
if the first in a series of tests throws an exception then all subsequent tests will fail
Its time consuming restarting the server and you have to be the person who breaks it to see the exception
if you are running a manual test deployment on a seperate machine then you have to restart the server if something caused a problem somewhere.
Likewise:
In production it will take everyone's application down and most users wont be in a position to restart the server.
What I'm doing instead
The errors were already being written the the tomcat logs + the database.
In debug we now also going to redirect to an error page with the stacktrace
In production we are going to just redirect to a 'something went wrong' page. We're also going to set up an email service that notifies us of exceptions.
For UI/selenium tests - it'll work the same as debug
For headless Js tests the server rejects subsequent requests until the next test resets the error state of the server
Just to make things more complicated unsurprisingly the original webapp is too flaky to not mask errors so I've kept the old error suppression in place for that as we're not actively developing/fixing it at the moment.

Is it any way to display custom 500-errors on App Engine (GAE)?

Server errors result in HTTP 500-responses to the client with a generic error message ("The server encountered an error..."). Is there any way to intercept this message and write a custom one?
I'm would like to have a way to uniquely identify a server error from the client. If I could for instance generate a GUID which I logged server-side upon a server error and then send that ID to the client, that would make it easy to search for that particular exception in the log at any point later in time.
I do realize that server errors are generated by exceptions in the code, so I'm looking for some kind of catch all exception hook in the app engine API. Of course, if such a hook exists, and the code which executes here generates a second exception, it would have to default to the general 500-error again.
I'm using the Java API for GAE
For GAE generated errors you can configure a custom error page. For errors generated by your code you should use a catch-all wrapper inside a first servlet filter.
I ended up coding a Servlet Filter by following the answer in this SO question. The filter wraps the doFilter() call in a general try-catch block and creates a reference number for the client while logging it at the server. I think this little snippet might be useful for others out there:
public class ExceptionFilter implements Filter {
private FilterConfig filterConfig;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
try {
filterChain.doFilter(request, response);
}
catch (Exception ex) {
String errorId = UUID.randomUUID().toString();
Mylog.e("Server error " + errorId); // Use whatever logging mechanizm you prefer
String clientResponse = "Server error. Reference no: " + errorId;
((HttpServletResponse) response).setStatus(500);
response.getWriter().write(clientResponse);
}
}
public FilterConfig getFilterConfig() {
return filterConfig;
}
public void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
public void destroy() {}
}
You also need to configure web.xml like this (goes somewhere under the <web app> tag):
<filter>
<filter-name>ExceptionFilter</filter-name>
<filter-class>your.package.ExceptionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ExceptionFilter</filter-name>
<servlet-name>Your Servlet Name As Defined In servlet-mapping</servlet-name>
</filter-mapping>
You didn't mention if your using python or java. Python error display https://developers.google.com/appengine/docs/python/config/appconfig#Custom_Error_Responses
Note these are just static pages that are shown in the event of any uncaught errors.
You can try and catch these errors in your main handler (I am talking about python), but you can't always. For instance you maybe able to catch a DeadlineExceededError some times, and you may have a tiny bit of time to emit a log, or a redirect (maybe to the same page to try again or to your own static page, with an arg with the GUID you mentioned, then have javascript render it some useful way) but often that won't work. So it very much depends on the nature of the error.

How do you to detect the end of a thread via ThreadId?

Talking Java Servlets here... I'm working on creating my own "Per Request Context" and I was looking to tie the "Per Request Context" object to the Thread.currentThread().getId() value.
Instead of passing around this context object everywhere I was planning on checking the current threadid when a user calls a function that is Per Request based and automatically getting the Context object out of a hashtable for that threadId.
I would use the code this like..
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
MyFramework.EnterContext();
try {
// do stuff here that leads to other classes on the same thread
// Access current context via static MyFramework.getCurrentContext()
}
finally { MyFramework.ExitContext(); }
}
However I would like to protect my application automatically from any potential user that does not call ExitContext(). In C# there is an event handler on the thread object for onexit...(think I wrong on this) is there some way to detect or poll when a thread exits? I'm currently storing only the threadId (long).
Any ideas?
unfortunatelly, there is no such feature built in for threads in Java. Besides, thread id is only guaranteed to be unique at any one time, but may be reused eventually when the thread dies (from the docs). however, the servlet framework that you are using may be implementing such feature (just a speculation).
i would recommend you implement a servlet filter, and tell your users to include it in their web.xml. with this you can be sure the client code always gets correctly wraped in your thread context.
A ThreadLocal seems to fit your use perfectly. A ThreadLocal object can provide a way to store a variable per thread. The internal workings of this class are very much of what you describe, it uses a map to give thread-local variables.
Something like this should do the trick:
private static final ThreadLocal<UserContext> userContext = new ThreadLocal<UserContext>();
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
MyFramework.EnterContext();
try {
UserContext context = userContext.get();
//if you used the set method in this thread earlier
//a thread local context would be returned using get
}
finally { MyFramework.ExitContext(); }
}
As for your other problem, you can use an observer pattern and notify when the thread completes its task.

Categories