Test Method with HttpServletResponse argument - spring

I have a method in my SpringBoot app, in GenerateZipServiceImpl class:
#Override
public void generateZipFile(final Parameters parameters, final HttpServletResponse response){
...
...
...
}
In this method I get request body as an Parameters object called parameters and I generate zip with some files(using this parameters to generate files).
I want to write some unit tests for this method. But I couldn't understand how to use this HttpServletResponse here(. Maybe I have to use Mockito or I don't know.
Can someone give me any suggestions?
This is the endpoint where I execute this method in my controller:
#PostMapping("generate")
#ResponseStatus(HttpStatus.OK)
public void downloadZipFile(#RequestBody final Parameters parameter, final HttpServletResponse response) throws FileReadingException, IOException {
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader(CONTENT_DISPOSITION, HEADER_VALUE_STR);
response.setStatus(HttpServletResponse.SC_OK);
this.generateZipServiceImpl.generateZipFile(parameter, response);
}

Related

Spring how create filter that reads body but keeps request intact [duplicate]

This question already has answers here:
How to get request body params in spring filter?
(2 answers)
Closed 4 months ago.
I need to calculate a value for every request body (soap requests) for this i created a filter (extending OncePerRequestFilter):
#Component
#RequiredArgsConstructor
public class AddHashFilter extends OncePerRequestFilter {
private final RequestHash hash;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
HttpServletRequest requestToUse = request;
if(!(request instanceof ContentCachingRequestWrapper)){
requestToUse = new ContentCachingRequestWrapper(request);
}
hash.hash(IOUtils.toString(requestToUse.getInputStream(), StandardCharsets.UTF_8));
filterChain.doFilter(requestToUse, response);
}
}
The problem is that this somehow destroys the request - i get 400. What i tried:
using request.geReader -> get an exception that getReader was already called
omit using ContentCachingRequestWrapper -> no change
i also tried this variant to read the body (from examples i found)
#Component
#RequiredArgsConstructor
public class AddHashFilter extends OncePerRequestFilter {
private final RequestHash hash;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
hash.hash(new String(StreamUtils.copyToByteArray(request.getInputStream()), StandardCharsets.UTF_8));
filterChain.doFilter(request, response);
}
}
The problem is same: all request are quit with 400.
But if i remove the actual work/ use of this filter (only keeping filterChain.doFilter...) it is working.
So how can i read complete body and keep it usable for everything after?
Http request could be read only once, so if you read it in filter you can not use it again. Spring provides its own class that extends HttpServletRequest and allows reading its contents multiple times. And that resolves your problem. See this question and my answer to it: How to get request body params in spring filter?

Springbook 2.0 interceptor forward to controller

I am building a small application in which I am trying to manage user login session.
My question is, is it possible to forward the http request from HandlerInterceptor.preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) method to controller
Something like this..
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
request.getRequestDispatcher("someController").forward(request, response);
return true;
}

Passin Parameters from Filter to Business Service in SpringBoot

I have 3 REST services which are reading some common header parameters on the request. I need to use that parameters on my business services. instead of reading that common header parameters on each web service controller (#RestController), Is it possible to read that headers on request filter and make it available on the business services ? If yes, are there any examples to do this ?
You can get request object
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
and access the headers in business services using request object.
Like #Nitin suggest you can pass the request object from your controllers to your services and read the header there. There is no problem with that.
If you still want to read it in a filter and have it available in any #Service you can do as follows:
#Component
#Order(1)
public class HeaderReaderFilter implements Filter {
#Autowired
private HeaderDataHolder headerDataHolder;
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
headerDataHolder.setHeaderContent(httpRequest.getHeader("header_field"));
chain.doFilter(request, response);
}
}
#RequestScope
#Component
public class HeaderDataHolder {
private String headerContent;
public String getHeaderContent() {
return headerContent;
}
public void setHeaderContent(String headerContent) {
this.headerContent = headerContent;
}
}
And then have the HeaderDataHolder #Autowired in your service classes. Notice the necessary #RequestScope so you have a different bean for each request.

Spring HttpServletRequest unaccessible in HystrixCommand

Inside a Javanica annotated #HystrixCommand we are checking if the request was in an actual HTTP servlet request by checking:
RequestContextHolder.getRequestAttributes() != null;
However invoked from a #HystrixCommand this condition is always false, even if the request came from a Spring MVC request.
If I remove the #HystrixCommand annotation everything works fine.
We also tried to use the HttpServletRequest directly, this works fine (without #HystrixCommand):
LOGGER.info(request.getHeader("X-Client"));
With annotated #HystrixCommand we are facing exception indicating I am not in an valid HttpServletRequest. I know it is due to Hystrix running commands in separate Threads from its own ThreadPool and tried to do this, but doesn't work either:
public class RequestServletFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
// No Impl
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HystrixRequestContext context = HystrixRequestContext.initializeContext();
try {
chain.doFilter(request, response);
} finally {
context.shutdown();
}
}
#Override
public void destroy() {
// No Impl
}
Does someone have a clue how to delegate the Spring HttpServletRequest into HystrixCommands?
Any help is appreciated.
When using the RequestContextHolder by default it parameters are not shared (for good reasons!).
Assuming that you are using a DispatcherServlet to handle your request you can set its [threadContextInheritable] to true to have the RequestContext and LocaleContext shared between requests.
The same applies for the RequestContextFilter, it isn't possible with the RequestContextListener.
Note: I would consider sharing the HttpServletRequest between threads as something you shouldn't be doing and should be done with great care!

Need to pass value from interceptor to handller in spring

Hey I am new to spring and I need help on below:
I have interceptor with prehandle and posthandle mehtods in it.I want to send some values to handller from interceptor.
suggest any idea.
Thanks.
You can achieve this as:
In your interceptor prehandle method:
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
...
HttpSession session = request.getSession();
session.setAttribute("attributeName", objectYouWantToPassToHandler);
....
}
In your handler handleRequest method:
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
....
HttpSession session = request.getSession();
objectYouWantToPassToHandler objectYouWantToPassToHandler = session.getAttribute("attributeName");
....
}
Actually, your question ins't clear, sorry. Try start from Spring AOP
And, of course, you have to show your code: what you have and what you want to do.

Resources