Converting a responseEntity to httpServletResponse with spring - spring

My controller method looks like this :
public void doLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
and I want to do this
ResponseEntity<String> responseEntity = restTemplate.postForEntity(testPrefix + "/login", map, String.class);
response = responseEntity;
or similar, basically make a restcall and return the HttpReponseEntity as the response n its enitirety

From updated comments I assume that you are wanting to return the result of the restTemplate.postForEntity() call from your Controller.
As shown by the Spring MVC documentation, ResponseEntity is a valid return type from a Controller method. So you can simply return the result of your restTemplate.postForEntity() call from the doLogin() method. As an example:
#Controller
public class MyController
{
#AutoWired
private RestTemplate restTemplate;
#RequestMapping("/yourPath")
public ResponseEntity<String> doLogin(HttpServletRequest request) throws IOException
{
return restTemplate.postForEntity(testPrefix + "/login", map, String.class);
}
}
Spring MVC will take care of marshalling the ResponseEntity into the HTML response using a HTTPMessageConverter.

Related

Why is a GET request mapped to "/error" in Spring-Boot?

When I send a GET request to /todo-list/user/list
it was mapped to /error.
Code
Interceptor:
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
RequestMapping classMapping = handlerMethod.getMethod().getDeclaringClass().getAnnotation(RequestMapping.class);
// when debugging: classMapping.value() was "${server.error.path:${error.path:/error}}"
RequestMapping methodMapping = handlerMethod.getMethodAnnotation(RequestMapping.class);
//some other codes
Controller:
//the contexPath is "/todo-list"
#RestController
#RequestMapping("/user")
#RequiredArgsConstructor
public class UserController
Method
#GetMapping(value = "/list")
public #ResponseBody Page<UserProjection> listGrid() {
return userService.listGrid();
}
I checked the address and method and whatever I think is the reason.
When debugging my code, classMapping.value() was equal to "${server.error.path:${error.path:/error}}".
What is the problem?

How to correctly mock Interceptor pre handle method in spring boot integration tests

I'm writing an integration test to an API which receives #RequestAttribute List<String> permissions and HttpServletRequest request as method parameters. There is a custom interceptor which overrides the preHandle() method of HandlerInterceptor. This method receives HttpServletRequest request and HttpServletResponse response as parameters. Based on some logic there are some attributes set in HttpServletRequest request.
I'm writing an integration test where in I send an Http request to the endpoint of the application. I want to mock the interceptor and set these attributes myself.
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#RunWith(SpringRunner.class)
public class TradeChargesTest {
#LocalServerPort
public int port;
#MockBean
AppInterceptor interceptor;
// other stuff
#BeforeEach
void initTest() throws Exception {
// Want to write the mock interceptor logic here.
}
public TestRestTemplate restTemplate = new TestRestTemplate();
public String createURLWithPort(String uri) {
return "http://localhost:" + port + uri;
}
}
Test method:
public class UserInfoControllerTest extends TradeChargesTest {
TestRestTemplate restTemplate = new TestRestTemplate();
HttpHeaders headers = new HttpHeaders();
#Test
public void testUserInfoController(){
HttpEntity<String> entity = new HttpEntity<String>(null, headers);
ResponseEntity response = restTemplate.exchange(createURLWithPort("Testing/endpoint/user/v5/getUser?from_date=2022-04-01&page=1"), HttpMethod.GET, entity, Object.class);
assertEquals(200, response.getStatusCodeValue());
LinkedHashMap<String, Object> responseBodyMap = (LinkedHashMap<String, Object>) response.getBody();
assertEquals(3, responseBodyMap.get("totalHits"));
assertEquals(1, responseBodyMap.get("page"));
}
}

Spring missing query parameters exception handling

I have this code:
#GetMapping(value = "/users/{id}")
#ResponseStatus(HttpStatus.OK)
public DtoUser getUserById( #PathParam("id") #PathVariable("id") #RequestParam Long id) {
return adminService.getUserById(id);
}
and this code:
#ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
#Override
public ResponseEntity<Object> handleHttpMessageNotReadable(
HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
return error_with_my_info;
}
#Override
protected ResponseEntity<Object> handleMissingServletRequestParameter(
MissingServletRequestParameterException ex, HttpHeaders headers,
HttpStatus status, WebRequest request) {{
return error_with_my_info;
}
...
}
The problem is that when I send a request WITHOUT a parameter, it is handleHttpMessageNotReadable that is called, not handleMissingServletRequestParameter.
Why is that?
Can other API endpoints affect this behaviour, like having a PUT request handler with the same endpoint?
How can I make it so that handleMissingServletRequestParameter?
Improvised :
#GetMapping(value = "/users")
#ResponseStatus(HttpStatus.OK)
public DtoUser getUserById( #RequestParam(value="id" , required=true)Long id) {
return adminService.getUserById(id);
}
localhost:8080?id=test
now if you dont pass id it will give you handleMissingServletRequestParameter.

Spring MVC, redirect to error after Rest call exception

I'm performing a Rest request in one of my controllers and I'd like to redirect to my error view if the request went wrong (404, 503 ...)
My controller calls this function :
public String functionTest(){
String date, res;
String url = "myRestUrl/{param}";
Map<String, String> uriParams = new HashMap<>();
uriParams.put("param", "param");
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
HttpEntity<String> request = new HttpEntity<>(createHeaders());
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new RestErrorHandler());
ResponseEntity<String> response = restTemplate.exchange(builder.buildAndExpand(uriParams).toUri(), HttpMethod.GET, request, String.class);
res= response.getBody().getMyResult();
return res;
}
And here is my Rest error handler :
public class RestErrorHandler extends DefaultResponseErrorHandler {
#Override
public void handleError(ClientHttpResponse response) throws IOException {
//Here I need to use a ModelAndView to redirect to error view but I'm not anymore in my controller
}
}
I guess I'm doing it wrong, do you have any solutions ?
Here is a rather simplistic way to achieve what you need. If you would like more control/flexibility, refer to this Spring blog article.
In your (client) RestErrorHandler:
public class RestErrorHandler extends DefaultResponseErrorHandler {
#Override
public void handleError(ClientHttpResponse response)
throws IOException {
// Do some stuff here ...
// This could be your own exception, for example.
throw new IOException();
}
}
Then in your controller (or refer to the article above if you want other options):
// Your requestMappings here ...
#ExceptionHandler(Exception.class)
public ModelAndView handleError(HttpServletRequest req, Exception ex) {
ModelAndView mav = new ModelAndView();
// Do stuff and redirect to your error view.
return mav;
}
EDIT: Another solution would be to catch Spring's RestClientException, which is a RuntimeException thrown by RestTemplate when it encounters an error:
try {
restTemplate.exchange(...);
} catch (RestClientException ex) {
// Do stuff here ...
}

Spring-MVC Exception handler returns OK when writing into response

I'm using spring-webmvc : 3.2.3.RELEASE (and its related dependencies).
I have this controller:
#Controller
#RequestMapping("/home")
public class HomeController {
#Autowired
MappingJacksonHttpMessageConverter messageConverter;
#RequestMapping(method = RequestMethod.GET)
public String get() {
throw new RuntimeException("XXXXXX");
}
#ExceptionHandler(value = java.lang.RuntimeException.class)
#ResponseStatus(HttpStatus.CONFLICT)
public ModelAndView runtimeExceptionAndView(ServletWebRequest webRequest) throws Exception {
ModelAndView retVal = handleResponseBody("AASASAS", webRequest);
return retVal;
}
#SuppressWarnings({ "resource", "rawtypes", "unchecked" })
private ModelAndView handleResponseBody(Object body, ServletWebRequest webRequest) throws ServletException, IOException {
ServletServerHttpResponse outputMessage = new ServletServerHttpResponse(webRequest.getResponse());
messageConverter.write(body, MediaType.APPLICATION_JSON, outputMessage);
return new ModelAndView();
}
}
since the "/home" method throws RuntimeException that is being handled with the #ExceptionHandler, when the get() method is invoked, I'm expectin to get HttpStatus.CONFLICT, but instead, I'm getting HttpStatus.OK.
Can someone please tell me what should I do in order to get the response status from
the annotated exception handler?
The reason is because you are explicitly writing to the output stream, instead of letting the framework handle it. The header has to go before the body content is written, if you are explicitly handling writing to the output stream, you will have to write the header also yourself.
To let the framework handle the entire flow, you can instead do this:
#ExceptionHandler(value = java.lang.RuntimeException.class)
#ResponseStatus(HttpStatus.CONFLICT)
#ResponseBody
public TypeToBeMarshalled runtimeExceptionAndView(ServletWebRequest webRequest) throws Exception {
return typeToBeMarshalled;
}
Modify ExceptionHandler method like this
#ExceptionHandler(value = java.lang.RuntimeException.class)
public ModelAndView runtimeExceptionAndView(ServletWebRequest webRequest, HttpServletResponse response) throws Exception {
response.setStatus(HttpStatus.CONFLICT.value());
ModelAndView retVal = handleResponseBody("AASASAS", webRequest);
return retVal;
}
If you want to handle exception by json result, I suggest to use #ResponseBody with Automatic Json return.
#ExceptionHandler(value = java.lang.RuntimeException.class)
#ResponseBody
public Object runtimeExceptionAndView(ServletWebRequest webRequest, HttpServletResponse response) throws Exception {
response.setStatus(HttpStatus.CONFLICT.value());
return new JsonResult();
}

Resources