NPE while using Custom Logging in Jetty 10/11 - java

I am implementing Custom logging in Jetty11 and getting the null pointer exception for the below code while fetching anything from the request object.
I know the reason but do not the solution to it. The reason is: calling the request object methods before setting it.
I know, there should be another way to do it.
My use case is to set the int and string attributes to the logger. In this example, I am calling request.getMethod() but I also have to call other methods as well
import org.eclipse.jetty.server.CustomRequestLog;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
public class JettyCustomLogger extends CustomRequestLog
{
private static Request request;
#Override
public void log(Request request, Response response)
{
this.request = request;
super.log(request, response);
}
public JettyCustomLogger(Writer writer, String logStr)
{
super(writer, setCustomAttributesToLog(logStr));
}
private static String setCustomAttributesToLog(String logStr)
{
String method = request.getMethod();
StringBuilder logBuffer = new StringBuilder(logStr);
logBuffer.append(method);
logBuffer.append("Ashish");
logBuffer.append(" ");
logBuffer.append("Goyanka");
logBuffer.append(" ");
logBuffer.append("absgdh");
logBuffer.append(" ");
return logBuffer.toString();
}
}
Note: this code works fine if I don't call request object methods.
Update: the reason to create setCustomAttributesToLog() is that I need to fetch the string parameters from other methods on runtime but here, I have given hardcoded string for code readability

The log(request, response) method is called for every request response pair, this method is expected to produce some formatted log string and then give it to the RequestLogWriter. You should not be using setCustomAttributesToLog() in the constructor as there is no request yet, and you should not be storing the request as a static field. All your logic to convert produce the log string based on the request must be done in the log() method.
For your current implementation, there should be no reason you cannot use the standard CustomRequestLog. If you read the javadoc on this class there is the concept of the format string. The format string is generic and takes % codes to be replaced with information from an actual request/response.
To get what you're trying to achieve here you could do something like
CustomRequestLog requestLog = new CustomRequestLog(writer, "%m Ashnish Goyanka absgdh ")
Then for each request the %m will be replaced with the request method, then this string will be given to the writer.
If you do not wish to use the format string functionality of CustomRequestLog I would suggest you implement the RequestLog interface directly instead of extending CustomRequestLog.

Related

Spring MVC Get POST body before controllers

I need to read POST requests body without consuming it.
I've tried it in a several ways in my custom HandlerInterceptor and nothing works. All I've tried to do to wrap and cache request bodies, at a some point, didn't work, probably even because I cannot control what Spring does.
So I thinked another thing: at some point Spring will try to map request body to an object and pass it to the right Controller. I can intercept this action and get that object before the Controller is called?
Once the request body is read from the request before reaching controller you can not use anywhere. So what you can do is to read the body from HttpServletRequest in the Filter implementation and set it in ThreadLocal variable. Then you can read from that ThreadLocal. Below is the sample code.
Inside Filter implementation class
try {
YourModel yourModel = // Read the request body
RequestContextHolder.setContext(yourModel);
}finally {
RequestContextHolder.clearContext();
}
and at any point of time in the current request you can do like below.
RequestContextHolder.getContext();
Here is the RequestContextHolder class
public class RequestContextHolder {
private static final ThreadLocal<YourModel> THREAD_LOCAL = new ThreadLocal<>();
public static void setContext(YourModel yourModel) {
THREAD_LOCAL.set(yourModel);
}
public static YourModel getContext() {
return THREAD_LOCAL.get();
}
public static void clearContext() {
THREAD_LOCAL.remove();
}
}
I've found a solution: using a CommonsRequestLoggingFilter Spring can log even the payload of the requests. The only bother I'm finding is that I can read the payload only in afterRequest method because in the beforeRequest is absent.
More info on CommonsRequestLoggingFilter here.

How to profile complex http request handling in Spring Boot?

I have complex #RestController method, something like this:
#PostMapping("{id}")
#PreAuthorize("hasRole('ADMIN')")
#Transactional
public Response handleRequest(#PathVariable("id") long id, #RequestBody #Valid Request request) {
return service.handleRequest(id, request);
}
Our request handling is quite slow so we want to check how much time is spent on particular request handling tasks. Unfortunately lot of things are done outside of my method, like:
deserializing request
validating
permission checks
starting and ending transaction
serializing response
Is there way to simply measure all those parts? Maybe set of loggers that receive trace messages so I can pull timestamps at the end of each step?
The only way I see to do it now is change that method to accept HttpServletRequest and HttpServletResponse and do those parts inside method body. But that way I will lose lot of Spring Boot benefits.
you can also check a tuto for adding a custom metrics for actuator, but it seems a little bit complicate (but you'll you have to code your own metrics bean and inject it in your code, override objectMapper for mapping, etc...
)
or maybe activate logging info on jackson,spring-security, javax.validation for checking the time in the log for each operation, but not very precise
what you exactly need is Java Thread Profiler which will tell you what is exactly going wrong and for it you can use any APM Tools and my favourite is GLOWROOT .which I have used in the similar scenarios to measure the performance of APIs and identify the slow traces which will clearly tell you which method is taking time and you can see the entire trace starting from method call to all the methods called inside and even identify slow queries if there are any . Hope this helps
Ths site: https://glowroot.org/
example trace :
https://demo.glowroot.org/transaction/thread-profile?transaction-type=Web&transaction-name=%2Fhot-sauces
There is no need to change the method to expect HttpServletRequest. You can use AspectJ
Using it, you can collect the time spent on each method and that analyze the data from it.
Create a methodTiming annotarion
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface MethodTiming {
}
In your Request, create a map that will keep all the methods and the time it took them:
public class Request {
private Map<String, Long> methodTimings = new TreeMap<String, Long>();
public void addMethodTiming(String classAndMethodName, long executionTimeMillis) {
Long value = methodTimings.get(classAndMethodName);
if (value != null) {
executionTimeMillis += value;
}
methodTimings.put(classAndMethodName, executionTimeMillis);
}
}
Than, create the Aspect class that will handle it:
#Aspect
#Component
public class MethodTimingAspect {
private static final String DOT = ".";
#Around("#annotation(MethodTiming)")
public Object timeAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object result = null;
StopWatch watch = new StopWatch();
try {
watch.start();
result = joinPoint.proceed();
} finally {
watch.stop();
long executionTime = watch.getLastTaskTimeMillis();
String className = joinPoint.getTarget().getClass().getSimpleName();
String methodName = joinPoint.getSignature().getName();
String classAndMethodName = className + DOT + methodName;
Object[] methodArgs = joinPoint.getArgs();
if (methodArgs != null) {
for (Object arg : methodArgs) {
if (arg instanceof Request) {
// inject time back into Request
Request request = (Request) arg;
request.addMethodTiming(classAndMethodName, executionTime);
break;
}
}
}
}
return result;
}
Finally, simply add the #MethodTiming on the methods you wish measure:
#MethodTiming
public Request handleRequest(Request request) {
// handle the Request
return request
}
Your request object will than have after the process something like
"methodTimings": {
"RequestService.handleRequest": 2610,
"AnotherRequestService.anotherMethod": 1351
}

Java library for converting rest urls to jax-rs methods

I have a collection of jax-rs resources, such as
#Path("/api/v1/ping")
public class PingResource {
#GET
public String ping(#QueryParam("name") String name) {
return "pong: " + name;
}
}
I want figure out how urls map into resource methods, e.g.
public class ResourceMethod {
Method method;
Object[] arguments;
}
public interface UrlToResourceMapper {
ResourceMethod mapToResource(HttpServletRequest request);
}
UrlToResourceMapper mapper = new UrlToResourceMapperImpl(Arrays.asList(PingResource.class));
ResourceMethod resourceMethod = mapper.mapToResource(new RequestImpl("GET", "http://host/api/v1/ping?name=josh", ...));
assertEquals(PingResource.class.getMethod("ping"), resourceMethod.method);
assertEquals(1, resourceMethod.arguments.length);
assertEquals("josh", (String)resourceMethod.arguments[0]);
Is there a library that implements something like the UrlToResourceMapper interface? e.g. Is there a class within Jersey that does this? Everything I've found so far either invokes the method, or only makes the method accessible from within the context of an executing request. I don't want to invoke the method, and I don't want to submit a request (I don't want filters to be invoked, for instance). I just want a library that tells me what invocation results from a given request.

How to set the values to one setter method using Reflection without knowing class?

I am new to java reflection.I will directly come to the question.
This is my class
public class RequestClass{
#XmlElement(name="Request")
private Request mRequest;
public Request getRequest() {
return mRequest;
}
public void setRequest(Request request) {
this.mRequest= request;
}
this my another class in this I am passing RequestClass object here
//The supplied requestObject is of type RequestClass
Object initialize(Object requestObject) {
//requestObject
}
In this code I want to manipulate, dynamically, the request property of the RequestClass. I don't know how to proceed further, so if anyone could provide some guidance, I would appreciate it. Thanks.
try this requestObject.getClass().getMethod(method_name).invoke(requestObject);
also, there is an overload of getMethod & invoke, through which you can pass parameter to that method (like in setters)

Change the body of a request

I have a Java Servlet, which is handling a REST request. However, this is breaking when it receives invalid data. This is POSTed in XML format, and to attempt to resolve this I have added a filter into the filter chain. The filter is being called, and I can access the data in the body of the request, accessing the XML.
I can validate this and manipulate it to ensure that the data is correct, but I cannot work out how to reset it back into the request object.
How can you set the body of an HttpServletRequest object?
You can wrap Your HttpServletRequest object with a new class lets name it: NewHttpServletRequest. The actual rewriting should be done in the appropriate overriden methods e.g getParameter(String)
package com.example;
import javax.servlet.http.HttpServletRequestWrapper;
public class MyHttpServletRequest extends HttpServletRequestWrapper {
public MyHttpServletRequest(HttpServletRequest request) {
super(request);
}
public String getParameter(String name) {
String str = super.getParameter(name);
// DO THE REWRITING
return str;
}
}
Take look at HttpServletRequestWrapper
You can wrap original request with a new object by using public HttpServletRequestWrapper(HttpServletRequest request) constructor, you won't have to do a lot work yourself.

Categories

Resources