问题
java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
As above mentioned I am getting an error in the line response .sendError() method. I have searched the internet for 4 days. But I couldn't figure out the problem. What can be the reason for this problem?
I have a custom exception class. In the following code, the catch block is successfully caught my custom exception. But when I try to send it to the client side it returns the exception mentioned above.
I have already tried Solution 1 – The Controller level @ExceptionHandler Solution 2 – The HandlerExceptionResolver Solution 3 – @ControllerAdvice Solution 4 – ResponseStatusException
Ways to resolve the above issue. But non-worked for me :(
I have added the error code and the error message to the response body. Then I can get the error successfully. But that is not the way I want.
@RequestMapping(value="/getMemberID/", method=RequestMethod.POST ,headers ="Accept=application/json")
public ResponseMemberID getMemberID(@RequestBody RequestMemberID request,HttpServletResponse response, @Context HttpServletRequest _request ) throws Exception {
Member_info memberinfo = new Member_info();
ResponseMemberID _response =new ResponseMemberID();
try {
memberinfo = memberinfoservice.getMemberID(request.getPin(),request.getMsisdn());
_response.setMember_id(memberinfo.getMember_id());
}catch(MemberNotFoundException exp) {
response.sendError(exp.getErrorCode(), exp.getErrorMessage());
}
return _response;
}
I need to get the error code and error message as a JSON response using above sendError() method. The exception is successfully coming to the catch block.
回答1:
Here, 1) You need to add error handler for custom exception 2) And error handler will throw exception
Some useful link: Recommended way of dealing with spring hibernate SQL errors
Is there a simpler exception handling technique for Spring?
Note: This approach is tested and I'm using it in my application.
@RestControllerAdvice
@RequestMapping(produces = "application/json")
public class DefaultExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(MemberNotFoundException .class)
@ResponseStatus(value = HttpStatus.CONFLICT)
public Map<String, String> handleConstraintViolationException(ConstraintViolationException ex) {
Map<String, String> response = new HashMap);
// set your response
return new ResponseEntity<>(response, ex.getStatus());
}
}
From, getMemberID
, remove try
and catch
block.
回答2:
@RestController
@CrossOrigin(origins = "*")
public class MemberController {
@Autowired
MemberInfoService memberinfoservice;
@RequestMapping(value="/getMemberID/", method=RequestMethod.POST ,headers = "Accept=application/json")
public ResponseMemberID getMemberID(@RequestBody RequestMemberID request) throws Exception{
Member_info memberinfo = new Member_info();
ResponseMemberID _response =new ResponseMemberID();
memberinfo = memberinfoservice.getMemberID(request.getPin(),request.getMsisdn());
if(memberinfo == null) {
throw new PINNotValidException();
}
_response.setMember_id(memberinfo.getMember_id());
return _response;
}
@ExceptionHandler(PINNotValidException.class)
public ResponseEntity<ErrorResponse> exceptionHandler(Exception ex) {
ErrorResponse error = new ErrorResponse();
error.setErrorCode(PSAExceptionCodes.PIN_VALIDATION_FAIL);
error.setMessage(ex.getMessage());
return new ResponseEntity<ErrorResponse>(error, HttpStatus.OK);
}
Above mentioned is the code I've changed according to the link http://www.jcombat.com/spring/exception-handling-in-spring-restful-web-service and it satisfies my problem.
Furthermore, I also tried using HttpServletResponse class's sendError() method in my application I created but it always returned an empty response.
But by using @ExceptionHandler for custom exception while creating separate PINNotValidException.class,ErrorResponse.class ,PSAException.class and PSAExceptionCodes.class I could easily solve my problem.Below mentioned are those classes respectively.
PINNotValidException.class
public class PINNotValidException extends PSAException{
private static final long serialVersionUID = 1L;
private static String errorMessage = "Pin Number and Mobile Number mismatch.";
private static int errorCode = PSAExceptionCodes.PIN_VALIDATION_FAIL;
public PINNotValidException() {
super(errorMessage, errorCode);
}
}
ErrorResponse.class
public class ErrorResponse {
private int errorCode;
private String message;
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
PSAException.class
public class PSAException extends Exception {
private static final long serialVersionUID= 100L;
private String errorMessage;
private int errorCode;
public String getErrorMessage() {
return errorMessage;
}
public int getErrorCode(){
return errorCode;
}
public PSAException(String errorMessage) {
super(errorMessage);
this.errorMessage = errorMessage;
}
public PSAException(String errorMessage, int errorCode) {
super(errorMessage);
this.errorMessage = errorMessage;
this.errorCode=errorCode;
}
public PSAException() {
super();
}
}
PSAExceptionCodes.class
public class PSAExceptionCodes {
public static final int PIN_VALIDATION_FAIL = 251; //Pin and mobile mismatch
public static final int ACCOUNT_TYPE_NOT_FOUND = 300; //Account type mismatch
public static final int NO_MEMBER_FOUND = 250; //Member Not Found
public static final int MEMBER_NOT_REGISTERED = 256; //Member not registered
}
来源:https://stackoverflow.com/questions/53954374/exception-occurs-when-i-try-to-pass-a-custom-error-to-client-in-spring-boot-appl