My application has several JAX-RS API, all of them are getting a transaction id as header, is there way we can access transaction id into Jboss Logger? we tried MDC but does that not help. Basically I am looking efficient way to add transaction id into each log.
You did not mention how you actually do the logging: explicit log. statements in the code, or some CDI/JAXRS interceptors...
A common way to achieve the desired functionality is to define a filter/interceptor on the boundary layer (JAX-RS in your case), that extracts the relevant request data and stores it in a context thats available to logger during execution of that request. Which is exactly what JAX-RS filters and MDC are for.
A simple example:
#Provider
public class TransactionLoggingFilter implements ContainerRequestFilter, ContainerResponseFilter {
#Context
HttpServerRequest request;
#Override
public void filter(ContainerRequestContext context) {
MDC.put("transactionId", request.getHeader("transactionId"));
}
#Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
MDC.remove("transactionId");
}
}
With that, you will store the value of your transactionId header in MDC scope before each HTTP request is processed and remove it after processing is complete.
Note: if you have other JAX-RS filters, you might need to configure priorities correctly (so that your logging extraction filter runs before others for example) see documentation
MDC scope is bound the thread that executes the request(careful if you use Quarkus reactive, make sure that it is propagated correctly) and will be passed to the logger impl with every log invocation.
To actually print out the value from MDC in your logs, you need to modify the Quarkus log format via:
quarkus.log.console.format=%d{HH:mm:ss} %-5p %X{transactionId} [%c{2.}] (%t) %s%e%n
You can access any MDC scope var with expression %X{var_name}.
See Quarkus documentation on logging for more info.
Related
I'm using spring data rest with #RepositoryRestResource where all the verbs are automatically handled for all the entities in the system.
There is no controller necessary for my project.
But I do want to perform certain action before the GET call is made to an entity. What is the best way to do this without writing a custom controller?
There are event handlers I can write in Spring Data Rest like #HandleAfterDelete but there are not handlers for GET.
I'm afraid there is currently no solution which would provide this out of the framework itself. However, there is a pull request which was discussed but not yet implemented as there are still open questions with regard to the universality of findBy* methods.
In case you do not need a that general solution the yet suggested HandlerInterceptor is the way to go…
public class YourInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler) throws Exception {
// decide on request.getMethod() what to do next
}
}
I wonder why spring boot inject same response object to my controller method parameter for different request, i use it like follow:
#Controller
#Slf4j
#Profile("default")
#RequestMapping("/test")
public class TestController {
#RequestMapping("/test")
#ResponseBody
public void getDeviceImage(#RequestParam("serialNumber") String serialNumber, HttpServletResponse response) {
return balabala;
}
}
I add a breakpoint before return command, and i find that response object's address is same for different request.
I want to write some thing to response.getOutputStream(), and i found there exists previous buffered data.
HttpServletResponse can be used if you need to add some extra meta information like cookies etc. By default even if you don't specify HttpServletResponse in the arguments, in typical MVC, model is added to the newly constructed response before propagating to the view.
If you just need to return some response back, say a model or entity or a simple JSON, you don't have to manually mess the HttpServletResponse. Unless you want to dig through cookies or headers etc.,. In your code, if you don't need to care about this, you might probably not need it.
As per the API doc for HttpServletResponse:
The servlet container creates an HttpServletResponse object and passes
it as an argument to the servlet's service methods (doGet, doPost,
etc).
What you see is probably the default configurations that Spring sets up.
With #ResponseBody, the return type is directly written back to response.
https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-responsebody
Finally, i find Response will been reused all the time, and Response's recycle method will been invoked for each request(org.apache.catalina.connector.Response#recycle).
But by default facade&outputStream&writer will not been cleaned, so i make system property "org.apache.catalina.connector.RECYCLE_FACADES" to be "true", after that issue disappears.
I'm planning to handle logging in spring.
Few suggest to handle it via LoggingInterceptor and some suggest to use AOP cross cutting concerns
which one is the recommended or best practice to follow for enterprise applications?
Thanks.
Both approaches have there own benefits and shortcomings. Logging via LoggingInterceptor is better approach as It is a standard library provided by Java to handle logging, you can do custom logging also.
AOP is better appraoch when you want to implement logging on more granular level as on certain return values of functions or classes. e.g if you want to log request only when the returning value is null. you can do it using AOP as :
#AfterReturning(pointcut = "execution(* com.foo.bar..*.*(..))", returning =
"retVal")
public void logAfterMethod(JoinPoint joinPoint, Object retVal) {
...
}
You can also do logging on returning value using Logging Interceptor but you need to write another function for that. i-e
public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object
arg3) throws Throwable {
log = LogFactory.getLog(arg3.getClass());
log.info("LOGGING IS: "+arg1.getName());
}
For production point of view AOP has performance overhead as you are adding overhead to execution of all your service calls. While Logging Intercept is just a class with normal execution cycle.
I need to store some data into the user session. Normally I would use getSessionMap().put() to solve this. My problem is, that I need to do this in the sessionCreated()-void of my sessionListener, but at this moment the FacesContext is still null. So the code below generates a NullPointerException.
#Override
public void sessionCreated(HttpSessionEvent arg0) {
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("data", "something");
}
Is there another way to store data into the session or can I initialize an instance of FacesContext manually? Unfortunately I don't know much about the jsf lifecycle.
Thanks for any help!
You seem to have completely missed the fact that JSF is merely one big abstract layer over the "plain" Servlet API and that ExternalContext (please take all time to carefully read its javadoc, including method descriptions) merely delegates to classes/methods available in "plain" Servlet API.
In your particular case, when you use JSF on top of Servlet API (instead of Portlet API), then the ExternalContext#getSessionMap() is merely a facade of HttpSession#setAttribute()/#getAttribute(). And guess what, HttpSession is in your HttpSessionListener readily available by the HttpSessionEvent argument!
#Override
public void sessionCreated(HttpSessionEvent event) {
event.getSession().setAttribute("data", "something");
}
This is then available by getSessionMap().get("data"), or by #ManagedProperty("#{data}") in any JSF backing bean, or just by #{data} in EL in a JSF page.
I am using Spring 3 AOP, and I have an aspect that requires access to the HttpServletRequest. It looks something like this:
#Aspect
public class MyAspect {
#Autowired
private HttpServletRequest httpServletRequest;
public void init() {
// Do something once...
}
#Before("my pointcut here...")
private void myMethod() {
// I need the httpServletRequest...
}
#After("my pointcut here...")
private void myOtherMethod() {
// I need the httpServletRequest...
}
}
And is configured like this:
<bean id="myAspect" class="com.some.package.MyAspect" init-method="init" />
Is the init method only called once per IoC container, even though this is an aspect, and is the httpServletRequest thread safe? If it is not, what is the best way to get at it during execution of the advice and have it be thread safe? If at all possible I prefer not to use a thread local.
Is the init method only called once per IoC container
It is called once per every bean instance. If bean has a singleton scope (which is the default case for aspects as well), it will only be called once. However you won't have access to the httpServletRequest inside init() method - there is no request yet!
is the httpServletRequest thread safe
It is not but don't worry. This is actually much more complex than it looks like. You are injecting HTTP servlet request (and obviously there can be several requests available at the same time) into a singleton object. Which one is injected? None (all?) of them! Spring creates some sophisticated proxy (called scoped proxy) and every time you access methods of injected httpServletRequest it delegates them to current (to thread) request. This way you can safely run your aspects in several threads - each will operate on a different physical request.
This whole behaviour is described in great details in 4.5.4.5 Scoped beans as dependencies:
[...] If you want to inject (for example) an HTTP request scoped bean into another bean, you must inject an AOP proxy in place of the scoped bean. That is, you need to inject a proxy object that exposes the same public interface as the scoped object but that can also retrieve the real, target object from the relevant scope (for example, an HTTP request) and delegate method calls onto the real object.
About ThreadLocal:
I prefer not to use a thread local.
Fortunately - Spring is using one for you. If you understand how ThreadLocal works - Spring puts current request into a thread local and delegates to thread-local instance when you access httpServletRequest proxy.