ServiceStack catch (WebServiceException ex) - has wrong ErrorCode - exception

In my ServiceStack service, I throw an exception that has an inner exception. When I caught a WebServiceRequest on the client side, the ErrorCode was the inner exception type name.
This is bad for me because it doesn't allow me to respond to the specific exception type that was thrown on the server.
I'm failing to see why ServiceStack was designed this way. It's pretty typical to catch lower level exceptions and wrap them with more informative and sometimes end-user friendly exceptions.
How can I change the default behavior so it uses the surface level exception and not the inner-most?

After looking at the first example at https://github.com/ServiceStack/ServiceStack/wiki/Error-Handling, I decided to check out at DtoUtils.HandleException, which looks like this:
public static object HandleException(IResolver iocResolver, object request, Exception ex)
{
if (ex.InnerException != null && !(ex is IHttpError))
ex = ex.InnerException;
var responseStatus = ex.ToResponseStatus();
if (EndpointHost.DebugMode)
{
// View stack trace in tests and on the client
responseStatus.StackTrace = GetRequestErrorBody(request) + ex;
}
Log.Error("ServiceBase<TRequest>::Service Exception", ex);
if (iocResolver != null)
LogErrorInRedisIfExists(iocResolver.TryResolve<IRedisClientsManager>(), request.GetType().Name, responseStatus);
var errorResponse = CreateErrorResponse(request, ex, responseStatus);
return errorResponse;
}
The very first instruction replaces the exception with it's inner exception. I'm not sure what the the thinking was with that. It seems counter intuitive to me and so I just re-implemented the method in my AppHost class, removing that first if statement block:
public override void Configure(Container container)
{
ServiceExceptionHandler += (request, exception) => HandleException(this, request, exception);
}
/// <remarks>
/// Verbatim implementation of DtoUtils.HandleException, without the innerexception replacement.
/// </remarks>
public static object HandleException(IResolver iocResolver, object request, Exception ex)
{
var responseStatus = ex.ToResponseStatus();
if (EndpointHost.DebugMode)
{
// View stack trace in tests and on the client
responseStatus.StackTrace = DtoUtils.GetRequestErrorBody(request) + ex;
}
var log = LogManager.GetLogger(typeof(DtoUtils));
log.Error("ServiceBase<TRequest>::Service Exception", ex);
if (iocResolver != null)
DtoUtils.LogErrorInRedisIfExists(iocResolver.TryResolve<IRedisClientsManager>(), request.GetType().Name, responseStatus);
var errorResponse = DtoUtils.CreateErrorResponse(request, ex, responseStatus);
return errorResponse;
}
This is obviously not ideal, since I had to copy a bunch of code that is totally unrelated to the problem that I had with the original implementation. It makes me feel like I have to maintain this method whenever I update ServiceStack. I would love to here of a better way to accomplish this.
Anyway, I have the exception handling that I like in my client code:
catch (WebServiceException ex)
{
if (ex.ErrorCode == typeof (SomeKindOfException).Name)
{
// do something useful here
}
else throw;
}

It doesn't seem like you'll have to maintain a bunch of code. You're writing one method to implement your own error handling. You could try calling DtoUtils.HandleException(this, request, exception) in your own method and modify the HttpError object returned. Not sure you have access to change all properties/values you're looking for.
public static object HandleException(IResolver iocResolver, object request, Exception ex)
{
HttpError err = (HttpError)DtoUtils.HandleException(this, request, ex);
err.Reponse = ex.InnerException;
}

Related

Handling Runtime Exception in CompletableFuture in java8

Below is the sample code I'm using to understand exception handling in completablefuture in java8.
If we make use of exceptionally method as per doc,
exceptionally method catches even runtime exception as well and proceeds to last block in the pipeline.
if we don't use exceptionally method then, it justs prints running and exits.
Correct me if my understanding isn't correct.
Question is Lets say if i want to throw runtime exception and want application to stop. Basically if i throw Runtime exception , it shouldn't proceed to next block in pipeline. How should i do that. Any pointers are helpful.
public static void main(String[] args) {
final CompletableFuture<String> retrieveName = CompletableFuture.supplyAsync(() -> {
System.out.println("running");
int i = 0;
if(i == 0) {
throw new RuntimeException("ding");
}
return "test";
}).exceptionally(it -> {
System.out.println(it.getMessage());
return "empty";
}).thenApply(it -> {
System.out.println("last block" + it);
return "dummy";
});
}
Try this:
public static void main(String[] args) {
try {
final CompletableFuture<String> retrieveName = CompletableFuture.supplyAsync(() -> {
System.out.println("running");
int i = 0;
if (i == 0) {
throw new RuntimeException("ding");
}
return "test";
}).exceptionally(it -> {
if (it.getMessage().contains("ding")) {
throw (RuntimeException) it;
}
System.out.println(it.getMessage());
return "empty";
}).thenApply(it -> {
System.out.println("last block" + it);
return "dummy";
});
retrieveName.join();
} catch (Exception e) {
System.out.println("main() exception, cause=" + e.getCause());
}
}
This is the output:
running
main() exception, cause=java.lang.RuntimeException: ding
I made 3 small changes to your code:
Wrapped it all in a try-catch
Threw a RuntimeException in exceptionally() for the "ding" exception.
Added a call to retrieveName.join(). From the Javadoc for CompletableFuture.join():
public T join​()
Returns the result value when complete, or throws an (unchecked) exception if completed exceptionally.
Update based on OP feedback ------->
Lets say if i want to throw runtime exception and want application to
stop. Basically if i throw Runtime exception , it shouldn't proceed to
next block in pipeline. How should i do that.
You can achieve what you want with just 2 changes to your code:
[1] Completely remove the exceptionally() callback so the CompletableFuture (CF) terminates with an exception. In exceptionally() in the OP code the exception was being swallowed rather than rethrown, and returning a CF, so the thenApply() method was still performed.
[2] Add a call to retrieveName.join() at the end of main(). This is a blocking call, but since the thread had terminated with an exception that 's not really relevant for the sample code. The join() method will extract the thrown RunTimeException and re-throw it, wrapped in a CompletionException.
Here's your modified code:
public static void main(String[] args) {
final CompletableFuture<String> retrieveName = CompletableFuture.supplyAsync(() -> {
System.out.println("running");
int i = 0;
if(i == 0) {
throw new RuntimeException("ding");
}
return "test";
}).thenApply(it -> {
System.out.println("last block" + it);
return "dummy";
});
retrieveName.join();
}
Notes:
This is not how to do things in Production. The blocking call from join() was not a problem here, but could be for a long running CF. But you obviously can't extract the exception from the CF until it is complete, so it makes sense that the join() call blocks.
Always bear in mind that main() is not running in the same thread(s) as the CF.
An alternative approach (if viable) might be to handle all the necessary post-exception actions (logging, etc,) within exceptionally() and then terminate normally with a suitable return value (e.g. "Exception handled!") rather than propagating the exception.
You can check whether the CF is still running by calling the non-blocking isDone() method. You can also check whether the CF ended with an exception (isCompletedExceptionally()) or was cancelled(isCancelled​()).

Exception Handling in java to show user the catch error message from the nested method calls

I have doubt in Exception handling in java,when the exception is thrown in the called method, how to show the catch error in the calling method
Yes, it is possible to catch exception inside called method, and then re-throw same exception back to caller method.
public String readFirstLineFromFile(String path) throws IOException {
try {
BufferedReader br = new BufferedReader( new FileReader (path));
StringBuilder lines = new StringBuilder();
String line;
while((line = br.readLine()) != null) {
System.out.println("REading file..." + line);
lines.append(line);
}
return lines.toString();
} catch(IOException ex) {
System.out.println("Exception in called method.." + ex);
throw ex;
}
}
Note: It is not possible if you are using try with resources, and exception occurred inside resources itself like opening of file, or file not found. In that case exception will be directly thrown back to caller.

Cannot handle FaultException by reflection invoking

I am preparing a client for WCF service.
I provoked an fault exception in some method on a service site. I mean:
throw new FaultException<sth>(new sth())
When I catch this exception in WPF appliction:
catch (FaultException<sth> ex)
{
// something
}
everything works very clearly.
My point is, that I made a reflection on the service interface.
var type = typeof (someServiceInterface);
type.GetMethods();
and I want to catch the FaultException, when I call the method service in this way
try
{
var singleMethod = //do sth to get method
var result = singleMethod.Invoke(proxy, parameters);
return result;
}
catch (FaultException<sth> ex)
{
//1
}
catch (Exception ex)
{
//2
}
But I catch an Exception in second catch, not in the first. The type of this Exception is "System.Reflection.TargetInvocationException". I am confused and I wonder what cause such kind of problem.

test "handled exceptions" junit

I have a method with a handled exception:
public boolean exampleMethod(){
try{
Integer temp=null;
temp.equals(null);
return
}catch(Exception e){
e.printStackTrace();
}
}
I want to test it
public void test_exampleMethod(){}
I have tried
#Rule
public ExpectedException expectedException=ExpectedException.none();
public void test_exampleMethod(){
expectedException.expect(JsonParseException.class);
exampleMethod();
}
but that doesnt work because the exception is handled inside.
I also tried
#Test(expected=JsonParseException.class)
but same issue...the exception is handled
I know that I can just do
assertTrue(if(exampleMethod()))
but it will still print the stack trace to the log. I would prefer clean logs...Any suggestions?
You cannot test what a method is doing internally. This is completely hidden (unless there are side effects, that are visible outside).
The test can check that for a specific input the method returns a expected output. But you can not check, how this is done. So you have no way to detect if there was a exception that you have handled.
So: either don't handle the exception (let the test catch the exception), or return a special value that tells you about the exception.
Anyway, I hope your real exception handling is more sensible than in your example.
If the method does not throw an exception you cannot expect to get one!
Below an example how write a Junit Test for a method that throws an Exception:
class Parser {
public void parseValue(String number) {
return Integer.parseInt(number);
}
}
Normal test case
public void testParseValueOK() {
Parser parser = new Parser();
assertTrue(23, parser.parseValue("23"));
}
Test case for exception
public void testParseValueException() {
Parser parser = new Parser();
try {
int value = parser.parseValue("notANumber");
fail("Expected a NumberFormatException");
} catch (NumberFormatException ex) {
// as expected got exception
}
}

How to catch the play.api.libs.openid.Errors$AUTH_CANCEL$ exception?

Using Play Framework 2.1 with OpenID, if I cancel my authentication from the OpenID Provider, I get this exception :
[RuntimeException: play.api.libs.openid.Errors$AUTH_CANCEL$]
Here's my code :
Promise<UserInfo> userInfoPromise = OpenID.verifiedId();
UserInfo userInfo = userInfoPromise.get(); // Exception thrown here
But since it's a Runtime exception, I can't catch it with a try/catch so I'm stuck on how to avoid exception and returns something nicer than a server error to the client.
How can I do that?
A Promise is success biased, for all its operations, it assumes it actually contains a value and not an error.
You get the exception because you try to call get on a promise which contains an untransformed error.
What you want is to determine if the Promise is a success or an error, you can do that with pattern matching for instance.
try this code:
AsyncResult(
OpenID.verifiedId.extend1( _ match {
case Redeemed(info) => Ok(info.attributes.get("email").getOrElse("no email in valid response"))
case Thrown(throwable) => {
Logger.error("openid callback error",throwable)
Unauthorized
}
}
)
)
You may want to read more on future and promises, I recommend this excellent article :
http://danielwestheide.com/blog/2013/01/09/the-neophytes-guide-to-scala-part-8-welcome-to-the-future.html
edit :
checking the documentation (http://www.playframework.com/documentation/2.1.0/JavaOpenID) in java it seems you are supposed to catch and handle exceptions yourself.
In any case, you should catch exceptions and if one is thrown redirect
back the user to the login page with relevant information.
something like this should work :
public class Application extends Controller {
public static Result index() {
return ok("welcome");
}
public static Result auth() {
Map<String, String> attributes = new HashMap<String, String>();
attributes.put("email", "http://schema.openid.net/contact/email");
final Promise<String> stringPromise = OpenID.redirectURL("https://www.google.com/accounts/o8/id", "http://localhost:9000/auth/callback",attributes);
return redirect(stringPromise.get());
}
public static Result callback() {
try{
Promise<UserInfo> userInfoPromise = OpenID.verifiedId();
final UserInfo userInfo = userInfoPromise.get();
System.out.println("id:"+userInfo.id);
System.out.println("email:"+userInfo.attributes.get("email"));
return ok(userInfo.attributes.toString());
} catch (Throwable e) {
System.out.println(e.getMessage());
e.printStackTrace();
return unauthorized();
}
}
}