Java 7: throw exception without stack trace - java

EDIT2
#paradigmatic made a good point in suggesting to redirect rather than throw the exception; that solves the logging issue. The problem in Play 2 is that redirects need to occur within so-called Action scope, which is not always the case with date parser calls.
As a workaround, I went with Play's global interceptor, presumably the equivalent of a Java servlet filter.
val ymdMatcher = "\\d{8}".r // matcher for yyyyMMdd URI param
val ymdFormat = org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd")
def ymd2Date(ymd: String) = ymdFormat.parseDateTime(ymd)
override def onRouteRequest(r: RequestHeader): Option[Handler] = {
import play.api.i18n.Messages
ymdMatcher.findFirstIn(r.uri) map{ ymd=>
try { ymd2Date( ymd); super.onRouteRequest(r) }
catch { case e:Exception => // kick to "bad" action handler on invalid date
Some(controllers.Application.bad(Messages("bad.date.format")))
}
} getOrElse(super.onRouteRequest(r))
}
EDIT
Here 's a little context to work with:
// String "pimp": transforms ymdString.to_date call into JodaTime instance
class String2Date(ymd: String) {
def to_date = {
import play.api.i18n.Messages
try{ ymdFormat.parseDateTime(ymd) }
catch { case e:Exception => throw new NoTrace(Messages("bad.date.format")) }
}
val ymdFormat = org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd")
}
#inline implicit final def string2Date(ymd: String) = new String2Date(ymd)
and a test custom exception handler:
public class NoTrace extends Exception {
static final long serialVersionUID = -3387516993124229948L;
#Override
public Throwable fillInStackTrace() {
return null;
}
public NoTrace(String message) {
super(message);
}
}
Calling the date parser on an invalid yyyyMMdd string logs 30 line stack trace to the log (this occurs upstream by Play framework/Netty container, better than default 100 line trace):
"20120099".to_date
ORIGINAL
Have an issue where my application.log is getting filled with errors related to a uri date parser operation that should succeed given a valid yyyyMMdd uri date.
However, some users try to circumvent this by entering invalid dates in hopes of gaining free access to paid subscriber-only content. It's pointless, as it simply won't work, but regardless, I have MBs of these error traces in my application log.
Is there a way to throw a truly trimmed down Exception to the log? I found this SO answer, but in my application it looks like the container (Play framework on Netty) gets into the mix and logs its own 30 line stack trace to the log (30 lines is better than 100, but still 29 too many)
Similarly, I found this thread in regard to Java 7 and the new option to suppress stack trace; however, for some reason, despite being on Java 1.7, with Eclipse configured for Java 1.7, only the old 2 param method of Throwable is available (and I do see the 4 param method when I click through to the Throwable class; maybe a Scala 2.9.2 library issue?)
At any rate, ideally I can simply log a 1-line exception message and not the kitchen sink.

Simply override this method in your custom exception class:
#Override
public Throwable fillInStackTrace() {
return this;
}
after adding this method your trace method will not print

Your trouble is that although you can suppress the stacktrace of the exception your own code threw, there is nothing you can do about the exception it will be wrapped into by the framework. The only avenue I can see is not allowing the framework to catch your exception at all (doing your own top-level handling) or tweaking the logging configuration.

I think you have two options:
Control the logging to not save stack traces for some exceptions.
Write a post-processor that filters out the traces from the log file.
Unless you are in danger of running out of disk space, I think #2 is the better option, because if you do have a bug you can go back to the full log and have all the exception history.
The philosophy behind idea #2 is that disk space is cheap, but information can be precious during debug. Log a lot of data. Normally, use scripts to examine the log after it has been written to disk.
For example, if there is a type of log entry that you never expect to see, but that demands immediate action if it does appear, write a script that searches for it, and send you an e-mail if it finds one.
One of the most useful forms of script in this approach is one that drops stack trace lines. Usually, you only need to know what exceptions are happening, and the stack trace takes up a lot of screen space without telling you much. If you do need to investigate an exception, go back to the full log, find the exception line, and look at the stack trace and at what was happening immediately before the exception.
If there are too many of your date exceptions, have the script drop even the exception line. If you want to track how often they are happening, run a script that counts date exceptions per hour.
That sort of script typically costs a few minutes of programming in your favorite regex-capable script language.

Related

Exception Handling in JS using Graal

I work on a Java application that makes fairly heavy use of Javascript to form the business logic/glue. It runs using Graal. This all works fine, but we struggle with effective error handling.
This is essentially how the JS is executed:
try {
Context context = Context.newBuilder("js").allowAllAccess(true).build()
Source s = Source.newBuilder("js", src, "script").build();
context.eval(s);
} catch (Exception e) {
LOGGER.error("Exception occurred in JavaScript:...", e);
}
So when errors happen we log them somewhere so we can do some postmortem, etc. It's possible to get the JS stack trace in these logs out of the PolyglotException that Graal throws, which is great. However, things are more complicated when some JS code has called back into Java-land, and a Java exception has been thrown:
var x = callJavaFunction("invalid parameter"); // Throws a NoSuchElementException, for example
The PolyglotException has an asHostException() method that returns the original Java-land exception, and my code that executes the JS files is smart enough to understand this and produce a useful error log. The problem arises when the JS code has tried to catch this itself, for whatever reason:
try {
var x = callJavaFunction("invalid parameter"); // NoSuchElementException
} catch (e) {
doSomeCleanup();
throw e;
}
Now we have lost the original Exception, and even worse, the JS-stack trace now just shows us the catch block, instead of where the cause was. isHostException() returns false, because this is just a JS error now. I cannot find a way to get at the original cause, which makes diagnosing errors quite difficult, especially when they have come out of a production system. The original Java exception message ends up in the JS-error object, which is helpful, but we don't have the stack trace, which is not.
What approaches can I take to try and address this?
One thought I had: Can I hook into the GraalVM and get a callback whenever a host-exception is thrown? At least that way I could have a log saying "the following Java Exceptions were thrown during execution" which I could attach to the error report. So far I've not been able to find a way to achieve this.

java File.createNewFile throws IOException before rest of program is executed occasionally

I have this project that I'm doing and for whatever reason, whenever I execute the program and put in the given arguments required for it (that I set and all) and occasionally an IOException is thrown before anything else is executed. It seems to be true because I got loggers everywhere and none of them are being fired. However, it seems that just the loggers are not being fired cause when I look in the json file I output to, it shows that it did do the first step of the execution, just no loggers. I'm new to log4j2 so it may be that but I'm not sure (with the loggers not being fired) but it seems weird that an IOException occurs when it shouldn't at all. Cause when I execute it again right after the crash, it runs just fine.
(Side note: this is in kotlin/jvm, but this is pertaining to the use of the JDK File class)
The exception is thrown here: https://github.com/AlexCouch/projauto/blob/master/src/main/java/thinkingcouch/projauto/Save.kt#L114
I'm on MacOSX High Sierra using Intellij IDEA 2017.3.
So what ended up happening was I had this function here for isolating a certain part of the given path to be appended to a new path and also saved to json for later use
fun Path.splitPathWithContext(context: String): File{
val presplit = this.normalize()
logger.info("presplit: $presplit")
logger.info("context: $context")
if(presplit.toString() == context){
logger.info("Path and context are the same.")
return presplit.toFile()
}
val reg = Pattern.compile("\\b$context\\b")
val ret = presplit.toString().split(reg)[1]
logger.info("ret: $ret")
return File(ret)
}
The solution was to do a strict pattern check against the context variable so that it doesn't cut at a word that contains that string but isn't that string exactly, and it needed to be exact. This solved my issue. No more problems, and no more broken paths, and I also fixed my loggers. I don't know exactly what was causing it to not do any logging, but I fixed it by setting the root level to "all" and then removing all my other logger elements since that's all I needed to do.

How to suppress Cucumber/Junit assertion stack trace

I have a cucumber scenario and the step uses assertEquals. My results report shows the stack trace which is not end user friendly. How can I suppress it
Scenario: Add two numbers
Given I have two inputs "3" and "2"
When I add them
Then the output should be "15"
You're correct in observing that the default XML output (assuming you're not outputting to JSON or text, but you didn't say) from a Junit tests show stack traces for failed steps. This isn't actually a Cucumber thing. CucumberOptions won't help you here.
You can:
Use a different or custom Runner for your test and then setup a tag that controls what is included in the output, or what will be read by the CI software of your choosing. For example the Confulence API API for doing this tells how "debugger"
Same type of deal for Ant Scripts to tweak the output, so that is doesn't show the output. A good Tutorial for learning how to use Any scripts to fire off your Cucumber JUnit Test is here.
Other have build a custom formatter for JUnit by implementing XMLJUnitResultFormatter API, explained more here - How do I configure JUnit Ant task to only produce output on failures?
Hope that gives you what you need.
I was also facing same issue with my Cucumber-Selenium-Java project. In the cucumber reports, it was generating around 40 lines of stacktrace. Due to this, it was impacting look and feel of the report. And the end user/client was little concerned about it. Because he/she was not really able to figure out the actual use of this stacktrace. So, I came up with below idea/approach. It's little bit tricky but, it's worthy.
Few notes before starting:
We cannot completely disable stacktrace in in all the cases. But we can modify the stacktrace and then, re-throw the new exception with useful and shortened stacktrace.
You need to be aware about frequently faced exceptions, errors. So that, we can create custom exception depending on the exceptions.
In the stacktrace it will generate few line of code from wrapper APIs, few lines from Junit/TestNg, few lines for java and selenium and there will be only one or two lines in the stacktrace, where actually our issue occurred.
Our test classes must be in unique package. So that, we can filter the stacktrace trace with package name and get the class name, line number and method name of actual issue and we can use this information in throwing custom exception. Hence, it will be easy to figure out the actual line of issue occurred. In my case all the classes were in package named "page". If you have more than one packages for your classes, then you can accordingly add string conditions in below code.
We need to wrap the test code in try-catch block. And while catching, we need to use Throwable class not exception class. Because, if there is any assertion failure, then Exception class won't be able to handle the issue as you know all the assertions come under Error class and Throwable is the parent of Error and Exception.
If we throw the new exception in catch block, then, it will change the line number in stacktrace, where actual issue occurred. So it will be difficult to figure out the actual line of issue. In order to avoid it, we need to get the class name, line number, method name of actual issue and store it in StackTraceElement class and use it in throwing new exception.
Some exceptions like "NoSuchElementException" provides lot of information in their cause and most of it is not really required, So we need to modify the content of it's message by using substring(), indexOf() and replaceAll() methods of String class in Java. And then, provide the modified information in new exception.
Few important Java method from Throwable java class and their description: (i) getStackTrace(): This method will return us array of StackTraceElement class. StackTraceElement class will provide us the class name, method name, line number at which issue is occurred. (ii) setStackTrace(): This method is used to provide a custom stacktrace to new Exception. (iii) getCause(): This method will provide the issue message from cause of exception. But sometimes, it might return null. Because for some exceptions "cause" might not be specified. So this needs be surround in try catch block and here we need to use getMessage() method for getting the actual error message. (iv) getClass(): This method will return the actual exception class name. We will use this method for figuring out the exception class name and then, we will use it for providing specific implementation for different different exception classes. Note: "getClass()" method is not from "Throwable" class. It is from Object class.
You need to create a common method for handling all the exceptions and reuse this method in all the required classes. e.g.: I have named the method as "processException" and placed it in "ReusableMethod" class.
Note that, I am using package name "page" in below method (line#8), because all my test classes are placed in this package. In your case you need to update the package name as per your need. Also, I have written custom cases for two exceptions only: NoSuchElementException & AssertionError. You might need to write more cases as per your need.
public void processException(Throwable e) throws Exception {
StackTraceElement[] arr = e.getStackTrace();
String className = "";
String methodName = "";
int lineNumber = 0;
for (int i = 0; i < arr.length; i++) {
String localClassName = arr[i].getClassName();
if (localClassName.startsWith("page")) {
className = localClassName;
methodName = arr[i].getMethodName();
lineNumber = arr[i].getLineNumber();
break;
}
}
String cause = "";
try {
cause = e.getCause().toString();
} catch (NullPointerException e1) {
cause = e.getMessage();
}
StackTraceElement st = new StackTraceElement(className, methodName, "Line", lineNumber);
StackTraceElement[] sArr = { st };
if (e.getClass().getName().contains("NoSuchElementException")) {
String processedCause = cause.substring(cause.indexOf("Unable to locate"), cause.indexOf("(Session info: "))
.replaceAll("\\n", "");
Exception ex = new Exception("org.openqa.selenium.NoSuchElementException: " + processedCause);
ex.setStackTrace(sArr);
throw ex;
} else if (e.getClass().getName().contains("AssertionError")) {
AssertionError ae = new AssertionError(cause);
ae.setStackTrace(sArr);
throw ae;
} else {
Exception ex = new Exception(e.getClass() + ": " + cause);
ex.setStackTrace(sArr);
throw ex;
}
}
Below is the sample Method to showcase the usages of above method in Test Class methods. We are calling the above created method by using the class reference, which is "reuseMethod" in my case. And we are passing the caught Throwable reference "e" to the above method in catch block:
public void user_Navigates_To_Home_Page() throws Exception {
try {
//Certain lines of code as per your tests
//element.click();
} catch (Throwable e) {
reuseMethod.processException(e);
}
}
Here are few screenshots for implementation of NoSuchElementException:
Before Implementing this approach:
After Implementing this approach:

How to write caller location information in a log file using Java, without hurting performance?

How can I write caller location information (Java source file and line), in a log file using Java and log4j, but without hurting performance?
log4j allow you to write such information in the log file, but it uses the stack trace to get that it information, every time a log statement is issued, what causes performance degradation.
I'm looking for a performance friendly alternative, like getting the location information at compile time instead at runtime. It is possible to use annotations to accomplish that? Or maybe some other technique?
How about making it part of the build process to replace certain placeholders, like $filename$ and $linenumber$ in this snippet.
logger.info("The original message... $filename$ $linenumber$");
To replace the filename, it may suffice to have keyword substitution with your revision control system. Disclaimer: this is just from the top of my head, I never tried it myself.
I agree with Rob that it is generally unnecessary. Usually there's some distinct string in a log message, searching for it will get to the source. With a good IDE this is really fast.
Now, given the question as is, this is a possible solution:
Class Foo
void bar()
new Logger(){} . warn("blah");
for each log action at runtime, a new object is created - that's not a problem.
for each line of source containing such log statement, a new class is created. that can be too many.
here's how the magic works:
abstract public class Logger
static Map<Class, String> sourceInfo = new ...
public Logger()
Class thisClass = this.getClass();
String info = sourceInfo.get(thisClass);
if(info==null)
info = ... // init from stack trace
sourceInfo.put(thisClass,info)
this.info = info
public void warn(msg)
log(WARN, this.info,msg)

How to get the stacktrace in a mobile device?

I'm getting a NullPointerException in a Nokia S40.
I want to know what is causing this exception.
The device shows:
NullPointerException java/lang/NullPointerException
This error only occurs in the device, running in the emulator the application works fine.
I use microlog to debug my application. But the application works fine if the log is enabled.
Is there a way to get the stack trace when I get this NullPointerException? I don't need all details like the line number just which method cause this exception.
UPDATE: I installed the same application in another Nokia S40 and the same error didn't occur.
Nokia 2660 - error
Nokia 6131 - no error
UPDATE 2: Somehow I find what was causing the NullPointerException.
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
public class OuterClass extends Canvas {
private Config config;
public OuterClass() {
this.config = new Config();
}
public void paint(Graphics graphics) {
HelperClass helper = new HelperClass(this.config);
helper.doStuff();
}
public void dispose() {
this.config = null;
}
public class Config implements IConfig {
public int getSomething() {
// ...
}
}
}
public class HelperClass {
private IConfig config;
public HelperClass(IConfig) {
this.config = config;
}
public doStuff() {
config.getSomething(); // Here is thrown NullPointerException
}
}
In some situations a thread is started and call the OuterClass.dispose() before the helper.doStuff() causing the NPE. I think when I enabled the log it made the thread slower and helper.doStuff() was called when I expected it to be called.
You are not going to find any way to save a Throwable stack trace on a Nokia Series40 handset.
The usual brute force way of debugging JavaME application on Series40 is to modify your code to create a stack trace yourself in memory.
What I'm talking about is:
Each Thread that you can identify (including system callback threads) needs its own Stack object, containing strings. Obviously, this increases the memory footprint of your application somewhat but keeping it in memory should limit the impact on race conditions.
When your code enters a method, it adds the method signature to the current Thread Stack. When the method exits (and you better only have one exit point per method) it pops the top of the Stack.
You can add aditional debug info on the stack, like values of variables in different places of the code.
You don't necessarily need to add this to every single method in your code.
You can add try{}catch(Throwable){} to the entry point of every thread you identified and either dump the stack in a file or on the screen (in a Form).
Obviously, this is not the kind of change you want to manually add in a lot of places in a large existing codebase. You can however make it part of your organisation coding standards for the future and write a source code parsing script to automatically add it to existing code.
I had some trouble in the past trying to print the stack trace to somewhere else than the standard output. The standard exception class doesn't provide the printStackTrace method that receives the output stream, therefore it only prints to the standard output stream.
It's possible, at least in Java SE, to redirect the java output stream to somewhere else by simply saying that System.out = . The PrintStream class receives an OutputStream, which means that you could create your own ByteArrayOutputStream, initialize a PrintStream, sets System.out to that stream, and then call ex.printStackTrace(). I don't have a J2ME environment here but I believe that, as long as it won't break when you try to set System.out to something else (nothing says that it's readonly in the docs), you should be able to do it.
After you do that, I would recommend writing it to a RecordStore that you have specifically for that, and then upload the records of that RecordStore to your server so you can get it.
I know it's not very easy but it may work. I would first test the System.out thing. If it works, everything else should work too.
My answer was wrong. As pointed out, the System.out and System.err fields are declared final. If you can't get the stack trace, and if you can't get the error when running the application on your emulator, try creating trace bullets on your code (alerts, logs, whatever you can) to isolate the piece of code where the problem is happening. It has to be something that could change between the emulator and the real device - for example, something related to retrieving/ saving records in a RecordStore, opening a Connection, etc... What did you try to do when you had the problem?
You could use Microlog to send an e-mail when the exception occurs.
Microlog
You could try catching the exception in some high-level try/catch block and then emailing the trace to yourself.

Categories