HttpServletResponse is null in Around advice,what did i do wrong? - java

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.

Related

How rewrite POST method on rest akka-http

I try to rewrite POST method from Spring to akka-http. To write akka-http minimal application I used tutorial - akka-http-quickstart-java. It has next routing:
post(() ->
entity(
Jackson.unmarshaller(User.class),
user ->
onSuccess(createUser(user), performed -> {
log.info("Create result: {}", performed.description);
return complete(StatusCodes.CREATED, performed, Jackson.marshaller());
})
)
),
Could you please help me add request, response to this routing, handling content TwimlMessageRequest and response with content type "application/xml" like in POST method in Spring API
#ResponseBody
#RequestMapping(method = RequestMethod.POST)
void GetMessage(#ModelAttribute TwimlMessageRequest twimlMessageRequest, HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException{
....
response.setContentType("application/xml");
response.getWriter().print(twimlResponse.toXml());

It's possible to send hidden parameters in HttpServletResponse.sendRedirect()?

I have a Spring Boot API (Stateless) with a Controller that receives a POST request, extracts the parameters of the POST request to send them through GET to my angular client. My question is if it's possible to send hidden parameters in HttpServletResponse.sendRedirect()?
What I have so far is this, but I do not want to show the parameters in the browser ...
#RequestMapping(value = "/return", method = RequestMethod.POST, headers = "Accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
#ResponseBody
#Transactional
public void returnData(UriComponentsBuilder uriComponentsBuilder, final HttpServletRequest request,
final HttpServletResponse response) throws IOException {
String parameter=request.getParameter("billCode");
response.sendRedirect("http://localhost:4200/payment?parameterOne="+parameter);
}
Update:
I can't uses HttpSession session = request.getSession(false); and then session.setAttribute("helloWorld", "Hello world") because session is Null
Many Thanks!
You can use the HTTP response header instead of sending the parameter in the queryString. An example:
#GetMapping(value="/")
public void init(HttpServletRequest request, HttpServletResponse response) throws IOException {
String billCode = request.getParameter("billCode");
response.addHeader("parameterOne", billCode);
response.sendRedirect("http://localhost:4200/payment");
}
To get the value from request:
String billCode = request.getHeader("parameterOne");
Or if you get from ajax with jQuery:
$.ajax({
url:'/api/v1/payment'
}).done(function (data, textStatus, xhr) {
console.log(xhr.getResponseHeader('parameterOne'));
});
Hope this helps.

What wrong with HttpServletRequest after .forward(req, resp)?

I have a test for simple Servlet which get jsp file. In this servlet action request.setAttribute("key", "value") but after call .forward() when I do request.getAttribute("key") I'm get null. Why this happen? This behavior determines forward or reason in mock object?
This is doPost of Servlet:
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
final boolean success = addUserInDatabase(req);
if (success) req.setAttribute("serverAnswer", EDIT_SUCCESS.get());//this write value
else req.setAttribute("serverAnswer", ERR_UNIQUE_L_P.get());
req.getRequestDispatcher(ANSWER.get())
.forward(req, resp);
}
This is test:
//mock http.
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
RequestDispatcher dispatcher = mock(RequestDispatcher.class);
when(request.getRequestDispatcher(ANSWER.get()))
.thenReturn(dispatcher);
servlet.doPost(request, response);
String result = (String) request.getAttribute("serverAnswer");//get value
Assert.assertThat(result, is(EDIT_SUCCESS.get()));// result == null
Why I get Null? Is it possible to get value of setAttribute after call forward? How to test this behavior? Thank You.
If you add String result = (String)req.getAttribute("serverAnswer"); just before calling req.getRequestDispatcher(ANSWER.get()) on your servlet and check value of result it would still be null.
The reason is your request object is not real but mocked. you have to do something like this.
when(request.getAttribute(eq("serverAnswer"))).thenReturn(EDIT_SUCCESS.get());
try request.getAttribute("serverAnswer").toString(); and use .include(request, response);.

How to define priorities for request mappings in Spring MVC?

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) {
// ...
}

get same session object in jsp and Servlet Filter?

I am setting an attribute to the session object in jsp page as shown below:
String remoteAddr = request.getRemoteAddr();
session.setAttribute("remoteAddr",remoteAddr);
Then, I am trying to retrieve that session attribute in the servlet filter:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String remoteIP = httpServletRequest.getSession(false).getAttribute("remoteAddr");
}
But I am getting a null value for the session object here. What is the correct way to get same session object here?
The method HttpServletRequest.html#getSession(boolean) may return null
If create is false and the request has no valid HttpSession, this method returns null.
A Filter may be invoked before a resource is requested or after it is requested depending on when you perform chain.doFilter(request, response);
In your case it seem that you query the session before the jsp is executed, i.e. doing something like this:
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String remoteIP = (String) httpServletRequest.getSession(false).getAttribute("remoteAddr");
// pass the request along the filter chain
chain.doFilter(request, response);
Changing it to
// pass the request along the filter chain
chain.doFilter(request, response);
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String remoteIP = (String) httpServletRequest.getSession(false).getAttribute("remoteAddr");
Will get it to work, but I doubt this is what you intend to do, since you probably want to check the remote IP and decide whether to allow access or deny it to the requested resource, in which case you may want to do something like this:
String remoteIP= request.getRemoteAddr();
if(remoteIP.matches("some pattern")) {
((HttpServletResponse)response).setStatus(HttpServletResponse.SC_FORBIDDEN);
} else {
// pass the request along the filter chain
chain.doFilter(request, response);
}

Categories

Resources