How to get httprequest and httpresponse in ApplicationListener in Spring Boot application? - spring

I would like to set browser cookie value after login successfully.
I am able to detect success login event with following code.
#Component
#Slf4j
public class LoginEventListener implements ApplicationListener<InteractiveAuthenticationSuccessEvent> {
#Override
public void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) {
log.info("hahaha: " + event.toString());
}
}

Try autowiring HttpServletRequest object into your LoginEventListener component, given that your component in running in a servlet container.
#Component
#Slf4j
public class LoginEventListener implements ApplicationListener<InteractiveAuthenticationSuccessEvent> {
#Autowired
private HttpServletRequest request;
#Override
public void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) {
log.info("hahaha: " + event.toString());
log.info("Request Object: " + request); // You now have access to the HTTP request object.
}
}

Tks, just share another way to get it.
HttpServletRequest request =
((ServletRequestAttributes) RequestContextHolder.
currentRequestAttributes()).
getRequest();

Related

spring boot interceptor for specific api, should not be invoked for all the api's

2 api's were exposed in a spring boot controller class. I have a requirement to intercept only 1 api and SHOULD NOT intercept other api. Can someone assist how to do this?
Below is the code
public class HeaderValidationInterceptor extends HandlerInterceptorAdapter{
private static final Logger logger = Logger.getLogger(HeaderValidationInterceptor.class);
//before the actual handler will be executed
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler)
throws Exception {
validateHeaderParam(request);
request.setAttribute("startTime", startTime);
return true;
}
}
Also I have a configuration class to add interceptor as below
Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
#Autowired
HeaderValidationInterceptor headerValidationInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(headerValidationInterceptor)
}
}
Controller class
#RestController
public class MyController {
#Autowired
private ICityService cityService;
#GetMapping(value = "/cities")
public List<City> getCities() {
List<City> cities = cityService.findAll();
return cities;
}
#GetMapping(value = "/cities/{cityId}")
public City getCityById(#PathVariable("cityId") String cityId) {
City city = cityService.findCityById(cityId);
return cities;
}
}
Inside your interceptor, you can check the request URI for the endpoint you want to intercept.
You can use a regular expression to match the URI. Following for /cities/{cityId} endpoint.
if (request.getRequestURI().matches("(\\/cities\\/[a-zA-Z0-9]+\\/?)")) {
validateHeaderParam(request);
request.setAttribute("startTime", startTime);
}
I'm not sure what is that want to do in your interceptor, but for your example you can do this inside your controller as well. Like this,
#GetMapping(value = "/cities/{cityId}")
public City getCityById(#PathVariable("cityId") String cityId, HttpServletRequest request) {
// Here you can use HttpServletRequest and do your validation
// validateHeaderParam(request);
// request.setAttribute("startTime", startTime);
City city = cityService.findCityById(cityId);
return cities;
}

Get Request/Response Body&Header in Spring AOP

I want to get request/response body and header within my aspect before and after if it's available or how to get those .
I mean i think with before annotation should be work for request,
with after annotation should be work for response. Can be ?
What I've tried so far :
I tried logbook library it's very complicated for me i could'nt figured it out how to work with that.So i gave up.
The actuator can do trick but I am doing extra work like how many times the endpoints called etc.So therefore i can't use actuator.
Also i tried to get request headers like below at least but i think this headers coming same all the time.I couldn't get httpservletresponse like how httpservetrequest does.
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
then
request.getHeader("date") but what about requestbody ?
how to get requestbody ? responsebody ? repsonseheader ?
My aspect file :
#Aspect
#Component
public class AppAspect implements ResponseInfo{
#Before("execution(#(#org.springframework.web.bind.annotation.RequestMapping *) * *(..))")
public void loggingStartPointRequests(JoinPoint joinPoint) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
}
#After("execution(#(#org.springframework.web.bind.annotation.RequestMapping *) * *(..))")
public void loggingEndPointRequests(JoinPoint joinPoint) throws IOException {
}
}
My Controller Class:
#RestController
public class MainController {
#GetMapping("/people") //
public ResponseEntity<Poeple> getAllPeople(#RequestParam(name = "page", required = false) Integer page,
#RequestParam(name = "size", required = false) Integer size,
#RequestParam(name = "sortBy", required = false) Boolean sortByNameOrEpCount) {
doSomething();
}
}
I had the same problem and if you have your #Aspect annotated with #Component (or any #Autowired candidate) you can simply get the HttpServletRequest like this:
#Aspect
#Component
public class SomeAspect {
#Autowired
HttpServletRequest request;
#Before("...")
public void beforeAdvice(JoinPoint jp){
/* You will have the current request on the request property */
System.out.println(request.getRequestURL());
}
}
I know this is an old question but I hope it'll be helpful.
I think what you need is to implement the interface HandlerInterceptor, it would help you being able to inspect the request and the response. For example:
public class ApiMonitor implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// when the client access to your endpoint
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
// when you finished your process
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// after you already returned an answer to the client
}
}
If you want to operate with the object that you're returning just before you send it to the client, then you need AOP, yes. That's an example of how I do it to modify an object on certain endpoints just before it's parsed to json.
#Component
#Aspect
public class MyCustomAOPInterceptor {
/**
* These poincuts check the execution of a method in any (*)
* class of my.package.controller and that start with
* get/list/find plus any other word (*) . For example
* my.package.controller.UserController.getUserById()
*/
#Pointcut("execution(* my.package.controller.*.get*(..))")
public void petitionsStartWithGet() { }
#Pointcut("execution(* my.package.controller.*.list*(..))")
public void petitionsStartWithList() { }
#Pointcut("execution(* my.package.controller.*.find*(..))")
public void petitionsStartWithFind() { }
#AfterReturning(pointcut = "petitionsStartWithGet() || petitionsStartWithList() || petitionsStartWithFind()", returning = "result")
public void translateEntities(JoinPoint joinPoint, Object result) {
// do your stuff; result is the object that you need
}
}

How can i use multiple interceptors for specific request such as POST, Get and PUT?

I am using spring boot and cloud in the project. For logging, I am using Interceptors. Since I am new to interceptors I am having difficulty using multiple interceptors. Like can I use a specific interceptor for the specific task? For example, when I request a post, the POST interceptor is called, when I use GET the get interceptor is called. and how can I code for multiple interceptors too?
I never tried anything yet for that because I am not getting the logic
You can define all HTTP interceptors that you want, every interceptor should implement the logic of intercept an HTTP request.
#Slf4j
#Component
public class GetRequestInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (request.getMethod().equals(HttpMethod.GET.name())) {
log.info("intercepting GET request {}", request.getRequestURI());
}
return true;
}
}
#Slf4j
#Component
public class PostRequestInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (request.getMethod().equals(HttpMethod.POST.name())) {
log.info("intercepting POST request {}", request.getRequestURI());
}
return true;
}
}
And then you have to register them in spring.
#RequiredArgsConstructor
#Configuration
public class WebConfigurer implements WebMvcConfigurer {
private final GetRequestInterceptor getInterceptor;
private final PostRequestInterceptor postRequestInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getInterceptor);
registry.addInterceptor(postRequestInterceptor);
}
}
#earandap
Your comment worked Thanks a lot.
Here is my code:
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
long startTime = System.currentTimeMillis();
request.setAttribute("startTime", startTime);
log.info("[START] [" + request.getMethod() + "] [ URL is: " + request.getRequestURL().toString()
+ " Body is: {}]");
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
long startTime = (long) request.getAttribute("startTime");
request.removeAttribute("startTime");
long endTime = System.currentTimeMillis();
log.info("[END] [" + request.getMethod() + "] [ URL is:" + request.getRequestURL().toString()
+ "] [Execution Time: {} miliseconds]", (endTime - startTime));
}

How to not use aspect in spring to write the request param and response param to the console

I found the class InvocableHandlerMethod.invokeForRequest will get the request param from request and invoke the controller class to get the return value.
What should I modify the method to write the params to the console?
I want to extends ServletInvocableHandlerMethod and override the method invokeForRequest but I can't call getMethodArgumentValues because it is private.should I copy the class of ServletInvocableHandlerMethod and InvocableHandlerMethod to modify the private method? Or is there have another way to log the request and response params without aspect?
Just create interceptor
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class LoggingInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// log here
return true; // let go further
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// log here
}
}
and register it
// example for Spring MVC annotation-based configuration
public class YourWebConfig extends WebMvcConfigurer {
...
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoggingInterceptor());
}
...
}

GWT - RemoteService interface and Spring - how to get HttpSession?

I am using GWT (2.5) with RPC, Spring and Postgresql for my project. My issue is about HttpSession handling .
All queries to server are dispatched by Spring (DispatchServlet) to my GwtController (extends RemoteServiceServlet) .
The particular RemoteService is injected in the GwtController . It is easy to get the HttpSession inside the GwtContorller.
In example by getThreadLocalRequest().getSession() or just from request.getSession().
My question is how to get HttpSession object inside the RemoteService ?
public class GwtRpcController extends RemoteServiceServlet {
……………
private RemoteService remoteService;
private Class remoteServiceClass;
………………
public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
…………
}
public String processCall(String payload) throws SerializationException {
…………
}
public void setRemoteService(RemoteService remoteService) {
…………….
}
}
My Interface - DataService which implements RemoteService
public class DataServiceImpl implements DataService {
public Data getData(){
!!!!! Here I want to get HttpSession !!!!!
…………………………
}
}
You can maintain a ThreadLocal in your Servlet and store there your current Request, then expose your Request with a static method.
public class GwtRpcController extends RemoteServiceServlet {
static ThreadLocal<HttpServletRequest> perThreadRequest =
new ThreadLocal<HttpServletRequest>();
#Override
public String processCall(String payload) throws SerializationException {
try {
perThreadRequest.set(getThreadLocalRequest());
return super.processCall(payload);
} finally {
perThreadRequest.set(null);
}
}
public static HttpServletRequest getRequest() {
return perThreadRequest.get();
}
}
public class DataServiceImpl implements DataService {
public Data getData(){
HttpServletRequest request = GwtRpcController.getRequest();
HttpSession session = request.getSession();
}
}

Resources