java - error - spring exception response
Devuelve HTTP 204 en nulo con spring @RestController (5)
Esto devuelve 200 OK con Content-Length: 0
@RestController
public class RepoController {
@RequestMapping(value = "/document/{id}", method = RequestMethod.GET)
public Object getDocument(@PathVariable long id) {
return null;
}
}
En pocas palabras, me gustaría devolver 204 No Content en null.
¿Hay una manera de forzar el spring-mvc / rest a devolver 204 en nulo no 200? No quiero cambiar todos los métodos de descanso para devolver ResponseEntity o algo así, solo mapeo nulo a 204
Misma respuesta pero resuelta por AOP:
@Aspect
public class NoContent204HandlerAspect {
@Pointcut("execution(public * xx.xxxx.controllers.*.*(..))")
private void anyControllerMethod() {
}
@Around("anyControllerMethod()")
public Object handleException(ProceedingJoinPoint joinPoint) throws Throwable {
Object[] args = joinPoint.getArgs();
Optional<HttpServletResponse> response = Arrays.asList(args).stream().filter(x -> x instanceof HttpServletResponse).map(x -> (HttpServletResponse)x).findFirst();
if (!response.isPresent())
return joinPoint.proceed();
Object retVal = joinPoint.proceed();
if (retVal == null)
response.get().setStatus(HttpStatus.NO_CONTENT.value());
return retVal;
}
}
Por supuesto que sí.
Opción 1 :
@RestController
public class RepoController {
@RequestMapping(value = "/document/{id}", method = RequestMethod.GET)
public Object getDocument(@PathVariable long id, HttpServletResponse response) {
Object object = getObject();
if( null == object ){
response.setStatus( HttpStatus.SC_NO_CONTENT);
}
return object ;
}
}
Opcion 2 :
@RestController
public class RepoController {
@RequestMapping(value = "/document/{id}", method = RequestMethod.GET)
public Object getDocument(@PathVariable long id) {
Object object = getObject();
if ( null == object ){
return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
}
return object ;
}
}
Podría tener errores tipográficos, pero entiendes el concepto.
Puede utilizar la anotación @ResponseStatus . De esta manera, puede tener un método de anulación y no tiene que crear una ResponseEntity.
@DeleteMapping(value = HERO_MAPPING)
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void delete(@PathVariable Long heroId) {
heroService.delete(heroId);
}
BTW devuelve 200 cuando existe el objeto y 204 de lo contrario, es un poco inusual con respecto al diseño de REST de API. Es común devolver un 404 (no encontrado) cuando no se encuentra el objeto solicitado. Y esto se puede lograr utilizando un ControllerAdvice.
En Spring REST es mejor manejar las excepciones con un controlador de excepciones en lugar de poner la lógica para decidir el estado de la respuesta, etc. Este es un ejemplo que usa la anotación @ControllerAdvice: http://www.jcombat.com/spring/exception-handling-in-spring-restful-web-service
Puedes probar esto:
@RestController
public class RepoController {
@RequestMapping(value = "/document/{id}", method = RequestMethod.GET)
public ResponseEntity<String> getDocument(@PathVariable long id) {
if(noError) {
............
return new ResponseEntity<String>(HttpStatus.OK);
}
else {
return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
}
}
}
Debe cambiar HttpStatus.BAD_REQUEST con el equivalente para el estado del código 204
Resolví este problema con un filtro. Es global y simple.
package your.package.filter;
import org.springframework.http.HttpStatus;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class NoContentFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
filterChain.doFilter(httpServletRequest, httpServletResponse);
if (httpServletResponse.getContentType() == null ||
httpServletResponse.getContentType().equals("")) {
httpServletResponse.setStatus(HttpStatus.NO_CONTENT.value());
}
}
}
y agrega lo siguiente en tu web.xml
<filter>
<filter-name>restNoContentFilter</filter-name>
<filter-class>your.package.filter.NoContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>restNoContentFilter</filter-name>
<url-pattern>/rest/*</url-pattern>
</filter-mapping>