I would like to extract the URI of an incoming request.
I have the following code in my application - a #RequestMapping which is #Async. I would like to extract the path URI via request.getRequestURI() but it returns null when the #Async annotation is present, otherwise, when it is not, the output is as desired. Is this intended behaviour, if so, why? And how can I obtain the same output with #Async? Removing #Async is not an easy option for me as I would like to use it for performance.
#Async
#RequestMapping("{name}/**")
#ResponseBody
public void incomingRequest(
#PathVariable("name") String name,
HttpMethod method,
HttpServletRequest request,
HttpServletResponse response)
{
String URI = request.getRequestURI(); // <-- null with #Async
}
It seems that in general, all request related parameters are being lost, which is not what I want; I need to extract them for my program.
The closest clue to the reason of empty HttpServletRequest I could find was comment to the answer on this post: What is a life of HttpServletRequest object?
To solve your issue you can try 2 approaches here:
Since your method is void you can manually start a new thread from incomingRequest method using, for example, CompletableFuture.
Or, try with returning CompletableFuture from your method, like so:
#Async
#RequestMapping("{name}/**")
#ResponseBody
public CompletableFuture<Void> incomingRequest(
#PathVariable("name") String name,
HttpMethod method,
HttpServletRequest request,
HttpServletResponse response)
{
String URI = request.getRequestURI(); // should get the right non null path
return CompletableFuture.completedFuture(null);
}
Related
I need request and response of API call, I'm getting all request params that I need but the response is always null, I need HttpServletResponse response to get request body how can I do that?
#Around("#annotation(Loggable)")
public Object loggable(ProceedingJoinPoint joinPoint) throws Throwable {
Object proceed = joinPoint.proceed();
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
ServletWebRequest servletWebRequest = new ServletWebRequest(request);
HttpServletResponse response = servletWebRequest.getResponse();
}
Assuming Loggable is custom annotation defined and used in the controller method, proceed variable defined in above block of code should have response of the API.
Currently , I am implementing the hreflang meta tag in my site and I am facing a problem , I need to create a method that must be executed in every page (in order to load the hreflangs into the model and pass them to the JSP) of my site and this method must have this parameters HttpServletRequest request, HttpServletResponse response.
I tried with this :
#RequestMapping(value = {"/*"})
public class GLobalPageController {
#ModelAttribute
public void setupHreflangs(Model model, HttpServletRequest request, final HttpServletResponse response) {
//code
}
}
But its not working , any idea about how can I achieve this ?
I have the following controller:
#Controller
#RequestMapping("/my-account")
public class AccountController {
#RequestMapping(value = "/foo/post",
method = RequestMethod.POST)
public String doPost(final RedirectAttributes redirectAttributes) {
redirectAttributes.addFlashAttribute("flashAttribute", "flashAttributeValue");
return "redirect:/my-account/foo/get";
}
#RequestMapping(value = "/foo/get",
method = RequestMethod.GET)
public void doGet(final HttpServletRequest request, final Model model) {
System.out.println("in request: " + RequestContextUtils.getInputFlashMap(request).get("flashAttribute"));
System.out.println("in model: " + model.asMap().get("flashAttribute"));
}
}
I would also like to access the flash attribute flashAttribute during the invocation of a filter in the filter chain that finally invokes springs default DispatcherServlet which in turn invokes AccountController.
public class FlashAttributeBasedFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain)
throws ServletException, IOException {
String flashAttribute = // how to access the redirectAttribute flashAttribute here?
// do something with flashAttribute ...
filterChain.doFilter(request, response);
}
The DispatcherServlet uses a org.springframework.web.servlet.FlashMapManager that handles these flash attributes, but it doesn't provide read-only access so I think I would be messing something up if I would use it in the filter. And also the FlashMapManager instance is kept in the dispatcher servlet privately.
Does anybody have an idea how I can make the redirect attribute accessible in the filter chain for the GET request succeeding the POST?
Considering that all these methods return null into my filter (I don't understand why):
RequestContextUtils.getFlashMapManager(httpRequest)
RequestContextUtils.getInputFlashMap(httpRequest)
RequestContextUtils.getOutputFlashMap(httpRequest)
I used a drastic solution: read directly the into the session (where flash attributes are stored).
CopyOnWriteArrayList<FlashMap> what = (CopyOnWriteArrayList<FlashMap>) httpRequest.getSession().getAttribute("org.springframework.web.servlet.support.SessionFlashMapManager.FLASH_MAPS");
if (what != null) {
FlashMap flashMap = what.get(0);
[read flashMap as you read a HashMap]
}
I know, this code is super ugly but at the moment I don't find another solution.
Had the same problem, following works for me.
FlashMap flashMap = new SessionFlashMapManager().retrieveAndUpdate(request, null);
flashMap.get("parameter");
Using SpringMVC, I have a method that catch all REST requests:
#RequestMapping(value = "/**")
public Object catchAll(#RequestBody(required = false) Object body, HttpMethod method, HttpServletRequest request, HttpServletResponse response) {
// ...
}
Now I would like to catch just a few requests with the following endpoint:
#RequestMapping(value = "/test", method = RequestMethod.POST)
public Object post(#RequestBody Object body, HttpMethod method, HttpServletRequest request, HttpServletResponse response) {
// ...
}
Right now, when I call:
/test
the second method is never called.
What can I do to have my 2nd method always called in place of the first one?
First of all as Asura points out, do not implement a 'catchAll' method. Having said that, Spring MVC allows you to use regular expressions in URL(s).
Read the documentation for using regular expressions in Spring URL(s) here.
In your case, use a negative lookahead in your first URL to remove the ones that start with /test. That way your /** controller will catch all requests except the ones that start with /test and you can use your other controller to catch those.
Use negative lookahead in your first URL:
#RequestMapping(value = "/^(?!test)")
public Object catchAll(#RequestBody(required = false) Object body, HttpMethod method, HttpServletRequest request, HttpServletResponse response) {
// ...
}
Now, this should catch /test requests:
#RequestMapping(value = "/test", method = RequestMethod.POST)
public Object post(#RequestBody Object body, HttpMethod method, HttpServletRequest request, HttpServletResponse response) {
// ...
}
i.e.
I have various URLs mapped using Spring MVC RequestMapping
#RequestMapping(value = "/mystuff", method = RequestMethod.GET)
#RequestMapping(value = "/mystuff/dsf", method = RequestMethod.GET)
#RequestMapping(value = "/mystuff/eee", method = RequestMethod.GET)
etc
I want to run some common action before about 90% of my requests. These are across several controllers.
Is there anyway to do that without delving into AOP? And if I have to use aspects, any guidance on how to do this?!
Thanks!
More info:
It is to run some app specific security - we are chained to a parent security set up, which we need to read and call into, and then need to access a cookie prior to some most of ours calls, but not all.
You can use an Interceptor:
http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-handlermapping
Interceptor is the solution. It has methods preHandler and postHandler, which will be called before and after each request respectively. You can hook into each HTTPServletRequest object and also by pass few by digging it.
here is a sample code:
#Component
public class AuthCodeInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
// set few parameters to handle ajax request from different host
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
response.addHeader("Access-Control-Max-Age", "1000");
response.addHeader("Access-Control-Allow-Headers", "Content-Type");
response.addHeader("Cache-Control", "private");
String reqUri = request.getRequestURI();
String serviceName = reqUri.substring(reqUri.lastIndexOf("/") + 1,
reqUri.length());
if (serviceName.equals("SOMETHING")) {
}
return super.preHandle(request, response, handler);
}
#Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
}
}
The HandlerInterceptor.preHandle() method gives you access to the request and response and also the target handler. In Spring 3.1 that will be of type HandlerMethod, which gives you access to the target controller class and method. If it helps you can try excluding entire controller classes by type name, which would be strongly typed and without specifying explicit URLs.
Another option would be created an interceptor mapped to a set of URL patterns. See the section on configuring Spring MVC in the reference documentation.