ServiceStack Can not get real exception message - exception

Server Side
public class MyServices : Service
{
public object Get(Hello request)
{
throw new InvalidOperationException("test error message");
//return new HelloResponse { Result = "Hello, {0}!".Fmt(request.Name) };
}
}
Client Side
try
{
var client = new JsonServiceClient("http://localhost:28586/");
var response = client.Get<HelloResponse>(new Hello { Name = "DHJ" });
}
catch (WebServiceException ex)
{
// ex.ErrorCode = "InvalidOperationException" // No Problem.
// ex.ErrorMessage = null // always null. Why?
}
And i saw the docs of ServiceStack like below:
Throwing C# Exceptions
In most cases you won’t need to be concerned with ServiceStack’s error handling since it provides native support for the normal use-case of throwing C# Exceptions, e.g.:
public object Post(User request)
{
if (string.IsNullOrEmpty(request.Name))
throw new ArgumentNullException("Name");
}
Default Mapping of C# Exceptions to HTTP Errors
By Default C# Exceptions:
Inheriting from ArgumentException are returned with a HTTP StatusCode of 400 BadRequest
NotImplementedException or NotSupportedException is returned as a 405 MethodNotAllowed
AuthenticationException is returned as 401 Unauthorized
UnauthorizedAccessException is returned as 403 Forbidden
OptimisticConcurrencyException is returned as 409 Conflict
Other normal C# Exceptions are returned as 500 InternalServerError
This list can be extended with user-defined mappings on Config.MapExceptionToStatusCode.

Your HelloResponse class needs a ResponseStatus property, from the Error Handling docs:
Error Response Types
The Error Response that gets returned when an Exception is thrown varies on whether a conventionally-named {RequestDto}Response DTO exists or not.
If it exists:
The {RequestDto}Response is returned, regardless of the service method's response type. If the {RequestDto}Response DTO has a ResponseStatus property, it is populated otherwise no ResponseStatus will be returned. (If you have decorated the {ResponseDto}Response class and properties with [DataContract]/[DataMember] attributes, then ResponseStatus also needs to be decorated, to get populated).
Otherwise, if it doesn't:
A generic ErrorResponse gets returned with a populated ResponseStatus property.

Related

How to return exception message with bad request status from webflux app

Could you please give me an advice, what is the proper way to return HttpStatus.BAD_REQUEST from webflux handler?
Here's the code, it seems to work properly, exception message returns as needed, but the response status is 200, while needed to be 400. Please note, that returning media type is TEXT_EVENT_STREAM -
#Component
public class ResolveHandler {
public Mono<ServerResponse> resolve(ServerRequest request) {
return ServerResponse.ok().contentType(MediaType.TEXT_EVENT_STREAM)
.body(
new ResultsFluxer(
Integer.valueOf(request.queryParam("numberOfIterations").orElse("0")),
request.queryParam("function1").orElse(""),
request.queryParam("function2").orElse(""),
orderingType
)
.getResult()
.onErrorResume(e -> Flux.just(e.getMessage()))
, Flux.class);
}
}

Should a server always send a JSON object as an http response?

I'm working on a node.js server using express and a android native app, using Retrofit 1.9.
For a login API that returns only a true/false answer to the client, should JSON still be used?
As I see it, the server has only to send a status code response:
if(isLegal) {
res.sendStatus(200);
dbConnector.updateUser(token);
}
else{
console.log('Token is not legal');
res.sendStatus(403);
}
But the Retrofit framework tries to convert the response to JSON, which makes me think I must send a JSON object with the answer, though it seems weird.
My retrofit restClient:
public class RestClient {
private static final String URL = SessionDetails.getInstance().serverAddress;
private retrofit.RestAdapter restAdapter;
private ServerAPI serverAPI;
public RestClient() {
restAdapter = new retrofit.RestAdapter.Builder()
.setEndpoint(URL)
.setLogLevel(retrofit.RestAdapter.LogLevel.FULL)
.build();
serverAPI = restAdapter.create(ServerAPI.class);
}
public ServerAPI getService() {
return serverAPI;
}
}
And usage:
restClient.getService().login(token.getToken(), token.getUserId(), new Callback<Void>() {
#Override
public void success(Void aVoid, Response response) {
Log.d("Chooser", "Successful login on server.");
}
#Override
public void failure(RetrofitError error) {
error.printStackTrace();
Log.d("Chooser", "Login failed on server.");
}
});
Using it as it is results with the following error:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
There are many topics on this issue but no certain answer about the correct (or better) method to use.
Any ideas about the best implementation in these cases?
Sending an empty body with your HTTP response is perfectly legal and some clients may care only about the response status but some clients may expect to get a response so sending a body never hurts and sometimes may be useful.
You can include a JSON response in addition to the HTTP response status:
// Express 4.x:
res.status(403).json({error: 'Token is not legal'});
// Express 3.x:
res.json(403, {error: 'Token is not legal'});
Such an error message can be very useful for the client development. You can get 403 for many reasons, illegal token, expired token, a legal not expired token but for the wrong user that doesn't have some privilege - adding a specific error message in addition to the HTTP response code can tell the client what exactly went wrong and allows the client-side code to show a better error message to the user.
Also, note that true and false are also valid JSON.

Send Exception and Json with spring MVC

I'm trying to manage exceptions in a Spring MVC context and send different http statuses in response.
I tried this :
#ResponseStatus(value = HttpStatus.SERVICE_UNAVAILABLE)
public class UnavailableServiceException extends RuntimeException {
}
When I send this exception in my controller, it works fine : response http status is 503.
But I want my controller to send json, and with this configuration, when 503 is send, response is html :-/
So I tried this :
Removing #ResponseStatus on my exception class and defining an Exception handler.
#ExceptionHandler(UnavailableServiceException.class)
public ResponseEntity<ExceptionJSONInfo> handleUnavailableService(UnavailableServiceException exception) {
return new ResponseEntity<ExceptionJSONInfo>(new ExceptionJSONInfo("Error xxx", exception.getMessage()), HttpStatus.SERVICE_UNAVAILABLE);
}
It's ok : 503 and json.
But I want to manage 5 or 6 different exceptions : how can I do this without duplicating handlers ?
Is it possible to retrieve #ResponseStatus defined on an exception ?
If not, my next idea will be to define an httpStatus attribute in a super class, mother of all my exceptions. And then :
public class UnavailableServiceException extends MySuperException {
super(HttpStatus.SERVICE_UNAVAILABLE);
}
#ExceptionHandler(MySuperException.class)
public ResponseEntity<ExceptionJSONInfo> handleUnavailableService(MySuperException exception) {
return new ResponseEntity<ExceptionJSONInfo>(new ExceptionJSONInfo("Error xxx", exception.getMessage()), exception.getHttpStatus());
}
Any better idea ?
Thanks
Manu

Jersey ParamConverter exceptions not handled by ExceptionMapper

Per title, exceptions thrown from a ParamConverter are NOT handled the way I expect.
With an ExceptionMapper:
#Provider
public class MyExceptionMapper implements ExceptionMapper<MyException> {
#Override
public Response toResponse(MyException exception) {
return Response.serverError().entity( "It triggered" ).build();
}
}
and ParamConverter:
#Provider
(boilerplate junk)
#Override
public DateTime fromString(String value) {
throw new MyException("convert");
}
It does NOT return the "It triggered" text in a 500 error, but rather a 404.
Anticipated question : Are both providers registered?
Yes - If I throw "MyException" from a resource (within 'regular' code) it works as expected. I can also convert see the stacktrace with the "convert" message.
Is there any way to make exceptions from ParamConverters be handled by the ExceptionMapper?
I am using jersey 2.3.1, along with spring-jersey, launched in a jetty container 9.1.0.RC0
Seem from reading this, the JAX-RS spec says the implementor should wrap unhandled exceptions in a NotFoundException (404) for #QueryParam and #PathParam, and from what I tested a 400, (I'm guessing BadRequestException) for #FormParam.
"if the field or property is annotated with #MatrixParam, #QueryParam or #PathParam then an implementation MUST generate an instance of
NotFoundException (404 status) that wraps the thrown exception and no entity"
A couple ways I can see handling the exception, is to
Just handle it in the ParamConverter, e.g.
return new ParamConverter<T>() {
#Override
public T fromString(String string) {
try {
return (T)new MyObject().setValue(string);
} catch (MyException ex) {
Response response = Response.serverError().entity("Boo").build()
throw new WebApplicationException(response);
}
}
#Override
public String toString(T t) {
return t.toString();
}
};
Or just have your exception extend WebApplicationException, and return the Response there. e.g.
public class MyException extends WebApplicationException {
public MyException(String message) {
super(Response.serverError().entity(message).build());
}
}
I experienced the same behavior in Jersey 2.26.
Any Exception that extends RuntimeException gets mapped to a ParamException, which is itself a sublcass of WebApplicationException.
Assuming your MyException extends RuntimeException, it's not getting caught because your ExceptionMapper only handles MyException.
Regarding the Jersey docs saying to throw a NotFoundException: I would argue a 404 does not apply when a queryParam can't be converted. A BadRequestException seems more appropriate. And also, I can't see anything unique in the Jersey frame work when a NotFoundException is thrown besides setting the response code
To get exceptions thrown from a ParamConverter end up in an ExceptionMapper, you'll have to have your ExceptionMapper catching a more global exception, like Throwable.
Another answer suggests returning a WebApplicationException. This should be a fine solution but will NOT work if the Response object has an entity. See here: https://github.com/jersey/jersey/issues/3716

Using ServiceStack unhandled exception behavior

I would like to get automatic exception serialization without manually adding ResponseStatus to the response DTO.
Based on this info on unhandled exception behavior I wrote the following code
public class ContactService : RestServiceBase<Contact>
{
public override object OnGet(Contact request)
{
return ContactApi.GetContactInfo(request);
}
//To trigger the serialization of the Exception to ResponseStatus
protected override object HandleException(Contact request, Exception ex)
{
throw ex;
}
<snip />
}
Do you see any issues with using the library in this manner?
Thanks in advance.
UPDATE: I would like to get the following response when there is an exception without having to add ResponseStatus property to my response DTO object.
I am able to achieve this with by overriding the HandleException method as shown above.
My question is:
Can overriding the default exception handling behavior in this manner cause any problems down the road?
{
"ResponseStatus":{
"ErrorCode":"ApplicationException",
"Message":"CRASH",
}
}