Seems like a fairly straight forward problem, but I'd like to log a stack trace when my top level error handler in Scalatra is triggered. I'm intentionally throwing an exception in one of my methods by doing something as trivial as:
throw new IllegalArgumentException
In the error handler, the code looks like the following:
error {
case e => {
val logger = LoggerFactory.getLogger(getClass)
logger.info("an exception occurred: " + e.getStackTrace())
logger.info("the request body is: " + request)
NotFound("An error occurred, please contact support")
}
}
The error handler itself is Scalatra specific, but I'm pretty sure the answer I'm looking for can be solved using any vanilla Scala technique. Is there something I can do at this point to grab the stacktrace? I'm not sure if the request is on the same thread as the error handler, otherwise there might be some answer there. e.getStackTrace() gives me [Ljava.lang.StackTraceElement;#1f6b6954
What's the best way to get a stack trace here printed out so I can log and review it to fix errors in my terrible code?
Use ExceptionUtils from Apache Commons Lang:
import org.apache.commons.lang3.exception.ExceptionUtils
(...)
logger.info("an exception occurred: " + ExceptionUtils.getStackTrace(e))
I think you want printStackTrace() rather than getStackTrace. If you are outputting to a log file, getMessage() may be helpful. Or you may try passing the whole exception object to the logger.
If you use the standard logger: com.typesafe.scalalogging.Logger , the logger prints the stack trace for you.
You can just use it this way:
import com.typesafe.scalalogging.Logger
import org.slf4j.LoggerFactory
try {
throw new Exception("test message")
} catch {
case e:Exception => logger.error("Exception " , e)
}
There is already an overload which is accepting 2 parameters, String and Throwable.
This question has several ways to convert an exception stack trace to a String. printStackTrace outputs to System.err unless you provide a writer.
Related
I have a verticle which accepts REST request, get data from other verticle through event bus and respond back to client.
vertx.exceptionHandler(event -> logger.error("Vertx exception ", event));
router.get("/api/v1/:param").handler(this::routerHandler);
public void routerHandler(RoutingContext rc) {
vertx.eventBus().request("data", param,
result -> {
if (result.succeeded()) {
logger.info("Request handled successfully");
// intentionally creating exception body() will return String
JsonObject jsonObject = (JsonObject) result.result().body();
rc.response().end(jsonObject)
}else{
logger.error("Request failed");
}
}
When a exception is raised it is printed in exception handler that I setup in vertx instance but after that the vertx is not reporting back the exception immediately to client instead it waits for timeout(30 secs) to occur.
I tried attaching error handler to router object and failure handler to route object but nothing helps to report the exception immediately to client. I know I can have a try catch and report the error in catch block. But I want know if there is any other way to handle this like Servlet or Spring MVC reports back to client even though the exception is not handled in code.
router.errorHandler(500,routingContext -> {
System.out.println(routingContext.failed());
routingContext.response().end("Exception ");
});
router.route().handler(BodyHandler.create()).failureHandler(routingContext -> {
Uncaught exceptions are reported to the context exceptionHandler. By default it prints the exception to the console.
You can configure it but you will not get a reference to the corresponding HTTP request anyway (the exception may come from different things).
Most problems like this are usually found during unit/integration/acceptance testing.
And for the remainders you could set a timeout handler on your router definition to make sure the request is ended before the default 30 seconds.
If you don't want to miss any uncaught exception, you should switch to the Vert.x Rxified API. When using RxJava, any exception thrown will be reported to the subscriber.
While running test (with Citrus or not) an exception may occurs if the test expects a message on a queue but the message isn't received before the timeout expires.
In this case I'd like know which line throws the Exception.
Unfortunatelly citrus doesn't show this information.
Here's my code :
#Test
#CitrusTest
public void testFail() {
sequential().actions(
mycheckNoError1(),
mycheckNoError2(),
mycheckNoError3(), //this one fails , we want to know it and which line throws the ActionTimeoutException
mycheckNoError4()
);
}
protected AbstractActionContainer mycheckNoError3() {
AbstractActionContainer aCatch = catchException().exception(ActionTimeoutException.class)
.when(receive("for_soap_q")
.timeout(100L)
.validationCallback(validationCallbackFunc()
))
.addTestAction(timeoutException(Thread.currentThread().getStackTrace()));
return aCatch;
}
And here's the stacktrace of citrus, that doesn't show the line that throws the exception:
...
INFO .c.r.LoggingReporter|
ERROR .c.r.LoggingReporter| TEST FAILED MyTest.test <package.test> Nested exception is:
com.consol.citrus.exceptions.ActionTimeoutException: Action timed out while receiving JMS message on 'testQueue'
at com.consol.citrus.jms.endpoint.JmsConsumer.receive(JmsConsumer.java:95) ~[citrus-jms-2.7.5.jar:na]
at com.consol.citrus.jms.endpoint.JmsConsumer.receive(JmsConsumer.java:60) ~[citrus-jms-2.7.5.jar:na]
at com.consol.citrus.jms.endpoint.JmsSyncConsumer.receive(JmsSyncConsumer.java:60) ~[citrus-jms-2.7.5.jar:na]
...
The only way I found was to pass the stacktrace as parameter of a method timeoutException() I wrote:
private TestAction timeoutException(StackTraceElement[] methodName) {
System.out.println("++++++++++ timeout Exception at line " + methodName[1].getLineNumber() + " in method: [" + methodName[1].getMethodName() + "]");
return null;
}
But I guess there is a better way to do this.
Is there a way to configure properly citrus and/or override the LoggingReporter to show the line number that make the exception happen ?
(in this case, this is the line: when(receive("for_soap_q")...)
thanks.
You can overwrite the default Logging reporter by placing a bean named 'loggingReporter' in the Spring application context. In addition to that you can add custom reporters and test listeners when choosing different bean naming. Just add the custom listeners to the Spring application context and they will get test events and throwable errors for reporting.
Also make sure to use the TestRunner fluent API instead of the TestDesigner fluent API. Designer is slightly more straight forward but runner will execute the test actions immediately while building the test case with the fluent API. So you will get more detailed stack traces with correct line numbers and the ability to set breakpoints for better debugging.
I'm trying to read a Cookie value in my server side implementation class. After some debugging my code now looks like this:
logger.info("Initiating login");
String oracleDad;
try {
logger.info("inside try");
oracleDad = Cookies.getCookie("dad");
logger.info("Read dad from cookie: " + oracleDad);
} catch (Exception e) {
logger.error("Failed to read dad from cookie", e);
oracleDad = "gtmd";
}
When I execute this code my onFailure block is fired with a Status code Exception:
com.google.gwt.user.client.rpc.StatusCodeException: 500 The call
failed on the server; see server log for details
My logging output on the server looks like this:
[INFO] c.g.e.server.rpc.MyProjectImpl - Initiating login
[INFO] c.g.e.server.rpc.MyProjectImpl - inside try
How is it possible that neither logger, the INFO or the ERROR, fire after the Cookies.getCookie() call? I'd hoped that by adding the catch(Exception e) I'd get some error message explaining why the code fails. But execution just seems to stop silently.
I'm using com.google.gwt.user.client.Cookies. I thought client code can be run on the server, just not vice versa. Is that correct? Is there something else I'm missing?
I'm using com.google.gwt.user.client.Cookies. I thought client code can be run on the server, just not vice versa. Is that correct? Is there something else I'm missing?
No, that's not correct, yes there is something you are missing: Server code can't run on the client, and client code can't run on the server.
You are not getting an Exception. You are getting an Error or some other Throwable.
Try catching Throwable in your try/catch block, and you'll see that you are getting an error where the server JVM is unable to load the Cookies class, because something is wrong. The JVM thinks that a native library is missing (because it doesn't know what JSNI is or how to run it), so it throws an UnsatisfiedLinkError:
Thrown if the Java Virtual Machine cannot find an appropriate native-language definition of a method declared native.
In GWT, the Cookies class is meant to interact with the browser itself to see what cookies have been defined on the currently loaded page. To use cookies on a J2EE server, ask the HttpServletRequest object for the cookies it knows about, and their values.
My Wildfly resteasy service is working fine, or was until I made a code change. No big deal, now I'm getting a deserialization error: "Problem deserializing 'setterless' property ..."
My question is whether there is anyway to get an error message in the client. I'm getting a Status of 400, and I can test that, but I'd like to get any message if possible. Any ideas?
If I get an error in the user code, I can set an error message in the header, but since there is a deserialization problem, the server is throwing a error before getting to any user code.
You can use an ExceptionMapper to handle the response returned to the client. JAX-RS has an exception hierarchy that will map to different responses and status codes. 400 in JAX-RS is a BadRequestException. So you could do something like
#Provider
public class BadRequestExceptionMapper
implements ExceptionMapper<BadRequestException> {
#Override
public Response toResponse(BadRequestException e) {
Response response = Response.status(Response.Status.BAD_REQUEST)
.entity("Sorry I forgot to implement a Setter").build();
return response;
}
}
This isn't a very great example, because BadRequestException is thrown for many other reasons, than just forgetting a setter (or deserialization), but it demonstrates how you can intercept the response after the exception is thrown.
See RestEasy Exception Handling
Jersey User Guider has a better explanation
See Exception Hierarchy
I am using Scala slick to work with my Mysql db.
I am wrapping all the calls using scala.util.Try
I would like to have different behaviour based on the problem
If the DB is down, ultimately I want my webapp to return a 503
If a strange query gets through to my db layer and there is a bug with my code then I want to return a 500
After some googling, it seems like you can get a wide array of different exceptions with error codes and I'm unsure what to look for.
With slick i am using the com.mysql.jdbc.driver
Thanks
Slick/MySQL will throw MySQLSyntaxErrorException for bad syntax and CommunicationsException when it's unable to reach the database.
Here's a quick example that will catch both of these types of exceptions:
try {
Database.forURL("jdbc:mysql://some-host:3306/db-name",
driver = "com.mysql.jdbc.Driver",
user="",
password="") withSession { session: Session =>
implicit val s = session
...
}
} catch {
case e: MySQLSyntaxErrorException =>
... handle the syntax error ...
// You may want to define your own Exception that wraps the MySQL one
// and adds more context
case e: CommunicationsException =>
... handle the connection error ...
}
Then, in your webapp code, you'll want to catch your custom exceptions (see the comment in the code) and return the HTTP codes accordingly.