Arun
Arun

Reputation: 619

How to produce error response in json

Am writing a Restful Webservice Impl, where i consume and produce response in JSON format by annotating @Produces("application/json"). Am producing JSON response as well. Here am handling exception with a class where it has error code and error message. When am getting exception it is not produced in application/json format. I used ExceptionMapper to find a solution but it is `text/plain format.

snippet

public Class Confiuration{
    @Path("getData")
    @Consumes("application/json")
    @Produces("application/json")
    public JSONGetDataResponseVo getData(GetDataRequestVo datarequestVO)
                                                          throws FaultResponse {
        JSONGetDataResponseVo response=new JSONGetDataResponseVo ();
        DataServiceValidator.validateGetConfigurationAndDataRequest(datarequestVO);
        ....
        ....
        }catch(ApplicationException applicationException){
            throw new FaultResponse(applicationException,locale);
        }  
}

FaultResponseMapper

@Provider
public class FaultResponseMapper implements ExceptionMapper<FaultResponse> {

    @Context
    private HttpHeaders headers;

    public Response toResponse(FaultResponse faultResponse) {
        return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(faultResponse).type(MediaType.APPLICATION_JSON).build();
    }

}

Application Exception

public abstract class ApplicationException extends Exception{

    private java.lang.String errorCode;

    public ApplicationException(String errorCode, String message) {
        super(message);
        this.errorCode = errorCode;
    }


    public ApplicationException(String message) {
        super(message);
    }



    public java.lang.String getErrorCode() {
        return this.errorCode;
    }


    public abstract String getLocaleMessage(Locale locale);

}

FaultResponse

public class FaultResponse extends WebApplicationException {

    private String errorCode;
    private String errorMessage;
    private String localErrorMessage;

    public FaultResponse(String errorCode, String errorMessage,
            String localErrorMessage) {
        this.errorCode = errorCode;
        this.errorMessage = errorMessage;
        this.localErrorMessage = localErrorMessage;
    }

    public FaultResponse(ApplicationException applicationException,
            Locale locale) {
        this.errorCode = applicationException.getErrorCode();
        this.errorMessage = applicationException.getMessage();
        if (locale != null
                && applicationException.getLocaleMessage(locale) != null) {
            this.localErrorMessage = applicationException
                    .getLocaleMessage(locale);
        } else {
            this.localErrorMessage = applicationException.getMessage();
        }
    }
}

So here how can i produce my faultResponse in JSON format.

Upvotes: 1

Views: 2114

Answers (1)

Paul Samsotha
Paul Samsotha

Reputation: 208994

This has to do with the fact that you are returning an exception as a response. I would

  1. Make an exception mapper for ApplicationException.
  2. Refactor FaultResponse to not extend and exception. Just create it in the mapper.
  3. In order to see the response, you will need to send a status other than No Content. You can't have a body in it. Send somethng like Bad Request.
  4. You can just declare the resource method as throws ApplicationException. You don't need to catch it and rethrow.

I've made these changes, and it works fine.


UPDATE: with complete test

Added getters (required for marshalling) to FaultResponse and remove the exception extension

public class FaultResponse {
    ...
    public String getErrorCode() { return errorCode; }
    public String getErrorMessage() { return errorMessage; }
    public String getLocalErrorMessage() { return localErrorMessage; }
    ...
}

Created a Service for testing and ApplicationException implementation

public class ApplicationExceptionImpl extends ApplicationException { 
    public ApplicationExceptionImpl(){
        this("400", "Bad Request");
    }

    public ApplicationExceptionImpl(String errorCode, String message) {
        super(errorCode, message);
    }

    @Override
    public String getLocaleMessage(Locale locale) {
        return "Bad Request";
    }  
}

public class FaultService {
    public void doSomething() throws ApplicationException {
        throw new ApplicationExceptionImpl();
    }
}

Resource class

@Path("fault")
public class FaultResource {
    
    FaultService service = new FaultService();
    
    @GET
    public Response getException() throws ApplicationException {
        service.doSomething();
        return Response.ok("Cool").build();
    }
}

ExceptionMapper

@Provider
public class ApplicationExceptionMapper implements ExceptionMapper<ApplicationException> {

    @Override
    public Response toResponse(ApplicationException exception) {
        FaultResponse response = new FaultResponse(exception, Locale.ENGLISH);
        return Response.status(Response.Status.BAD_REQUEST)
                .entity(response).type(MediaType.APPLICATION_JSON).build();
    }  
}

ApplicationException class is left the same

curl -v http://localhost:8080/api/fault
{"errorCode":"400","errorMessage":"Bad Request","localErrorMessage":"Bad Request"}

If after this you are still not seeing JSON, it's possible you do not have a provider configured. If this is the case, please show your application configuration, along with your project dependencies.

Upvotes: 1

Related Questions