2 Questions:
What is the difference between e.printStackTrace(System.out) and e.printStackTrace() ?
Is it safe (from the production point of view) to replace e.printStackTrace(System.out) and e.printStackTrace() with log4j using logger.error("", e) if i want to print out the stack trace in my log file?
e.printStackTrace() is same as e.printStackTrace(System.err). So, it prints to standard error. e.printStackTrace(System.out)` prints to system out.
You should never do e.printStackTrace(), System.out.print(), System.err.print() on a production code. You should always use logger methods, and configure your logger.
Related
I need to get output result (FAIL or SUCCESS) into log4j output.
Assert.assertTrue(availresponse);
Is there any way to add TestNG console output into log4j.log file?
I found a simple, easy and perfect way to log TestNG output into log4j.log file. But this can't be log Final Report Details into log4j (PASS or FAIL).
implements ITestListener
Then add unimplemented methods
public void onTestSuccess(ITestResult result) {
logger.info(result);
}
public void onTestFailure(ITestResult result) {
logger.info(result);
}
You can add log4j logger in the methods you need. Enjoy!
If you need that, you could use if .. else construct to do the logging.
if(null != availresponse) {
//log success message
} else {
//log failure message
}
Another way is to write a custom class implementing TestListenerAdapter. You can see full example code here.
Wrap the assert with a logger e.g.
log.info(Assert.assertNotNull(availresponse));
However this is a bit limited in terms of information. What I usually do is:
if(availresponse==null)
{
log.fatal("availresponse was null");
}
Assert.assertNotNull(availresponse);
I know it's a bit of a hassle, testing for the condition twice but it does allow you to tweak the output level of the logger and add any other information you think would be useful e.g. the variables which were used to determine the contents of availresponse.
Alternatively you could try getting the console output to appear in your log file in which case you'll need to add something like:
log4j.appender.stdout.Target=System.out
to your log4j properties file.
You can find test-output folder in your project PATH. index.html will show the Test output of Success or Fail.
If the testMethod() is Success, there will no any output result shows in index.html file. You can add Success message by using Reporter.log()
If testmethod() fail, automatically it will prints output in file.
NOTE : java.lang.AssertionError is an error that thrown to indicate that an assertion has failed.
If anyone know how TestNG inserting that error to the report, comment below.
Finally found the easiest way to log the Assert error in log4j
In catch block it should be Throwable, if it is Exception that will not work.
try {
Assert.assertTrue(hotel.getAmenitiesList().size() < 0, "Hotel Amenities Available!");
} catch (Throwable e) {
e.printStackTrace();
logger.error("FAILED: testRoomAmenities ", e);
Assert.fail();
When this implement that will not invoke as FAIL. It will show that scenario is PASSED. Therefore you should use Assert.fail() to make that is FAILED
i recently started using sonar as code review tool.
When i analysed my code running sonar,
it reflected printing stack trace as violation of java coding standard.
As an alternative to stack trace, I tried:
e.getcause()
but this did not clear the exception as done by stack trace
Error handling can be tricky in any environment, java included. I haven't used sonar, but I can comment on general good practices for java error handling.
e.printStackTrace() is generally discouraged because it just prints out the stack trace to standard error. Because of this you can't really control where this output goes.
The better thing to do is to use a logging framework (logback, slf4j, java.util.logging, log4j, etc) because then you can control where the errors are logged to and what the log retention policy is.
And generally you'll want to catch the exception and if it's unexpected behavior, log it and either throw a new exception (probably specific to your application) or do whatever you have to do to continue operating gracefully.
If you're using java.util.logging, you can do something like the following:
class YourClass
{
Logger logger = Logger.getLogger(YourClass.class.getName());
...
public void someMethod() throws YourException
{
try
{
// your code here
} catch (NullPointerException e)
{
String message = "Unexpected NullPointerException in processing!";
logger.log(Level.ERROR, message, e);
throw new YourException(message, e);
}
}
}
Hope this helps!
A few thoughts:
I presume from the title you were using e.printStackTrace(). This does not "clear the exception", so I'm not sure exactly what your issue really is on that point. In java "clear the exception" doesn't make any sense at all in this context.
e.printStackTrace() is "not a good idea" because it writes to standard out. Much better to write such detail to a log file for later diagnostics, rather than put it out in front of a user (though that could depend on how the program actually runs). Your run-time environment may have something to say about use of standard output.
e.getCause() will return, if available, an "underlying exception" that may have been a "root cause" for the exception e. Must stack traces will show this after an initial stack dump denoted by "Caused by: : ..."
If you choose to try to capture and display/log an exception yourself - you might use e.printStackTrace(PrintStream s) or e.printStackTrace(PrintWriter s).
You'd be best served using a logging tool, as suggested by Matt.
I have a method that sometimes throws an exception:
this.items[index] = element;
And I have a unit test that asserts that the exception that ought to be thrown is actually thrown:
try
{
doSomethingWithIndex(-1);
Assert.fail("should cause exception");
}
catch (IndexOutOfBoundsException expected)
{
Assert.assertNotNull(expected.getMessage());
}
This test runs as part of the continuous build and sometimes, occasionally it fails because getMessage() in fact returns null. Why would this happen? My code can never throw an exception with a null message.
EDIT
My original code example was misleading, the thrown exception is actually coming from directly indexing an array. I can reproduce the same behavior with a custom thrown exception though.
I added the suggested code:
catch (IndexOutOfBoundsException expected)
{
if (expected.getMessage() == null)
{
expected.printStackTrace();
}
Assert.assertNotNull(expected.getMessage());
}
The console output is missing the stack trace in addition to the cause. Here's the full output:
java.lang.ArrayIndexOutOfBoundsException
Found the answer on a similar question.
The JIT compiler will optimize away stack traces in certain exceptions if they happen enough.
The JVM flag -XX:-OmitStackTraceInFastThrow prevents this behavior and seems to fix the flickering unit tests.
Try printing stack trace of exception when it has null message. It's possible that some other code throws it. Like you actually accessing past array length.
You wrote that:
"My code can never throw an exception with a null message"
Are you yousing any 3rd party library? I assume standard java codes never throw exceptions like this above, but some pourly coded jar... :)
In my code base is the (very simplified) following:
public static void main (String[] args) {
System.out.println("Starting application");
try {
System.out.println("About to validate");
validate(args);
catch (Exception e) {
e.printStackTrace();
}
}
public static void validate(String[] args) {
System.out.println("Your first arg is " + args[0]);
if (someProblemWith(args)) {
System.out.println("Your args are wrong. It should be: ...");
throw new BadArgsException(e);
}
}
Which works fine. Note that my example code above is contrived and simply meant to show multiple log statements prior to exception and stack trace printing. This often means that my last logging statement is lost in the middle of the stack trace output. Is there an elegant way to ask the e.printStackTrace() statement to wait until the System.out has finished its work? I'm essentially looking for the stacktrace to be the very last thing printed when an error occurs. Here's a sample output of my program above:
java.lang.Throwable
....
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
Your args are wrong. It should be: ...
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:56)
The reason you are seeing the stack trace being printed between the System.out.println() statements, is because System.out is buffered, while System.err (used by stack trace) is unbuffered.
If you want the text to be displayed in the exact order in which things are happening, you need to "unbuffer" the System.out. The simplest way is to also just use System.err there instead of System.out.
Otherwise, call System.out.flush() before your stack traces happen in the catch clauses.
Option 2: Use the Logger class.
Option 3: Implement your own "buffer". In other words, first write everything to your own buffer, including the stack traces (using .toString() or however you wish) and then in the catch flushing you own buffer. (This is kind of redundant since you can just flush the System.out anyway).
-==-
FROM COMMENT
Sure. The Logger class can be used to create a much more robust and detailed logging experience. This is typically what is done in applications. An instance of the Logger class is grabbed from the Logger class (it is a singleton), taking as parameter the class from which is will be used. Then you log messages to it by using the .log() method. The nice thing about the Logger class is that you can set levels on it (example DEBUG, WARN...) and you are then able to filter / display only what you want. The "log" messages are then displayed in a uniform way in the console, typically in the format of:
2010-11-23 14:45:32,032 DEBUG [MyClass] Your message
The above format is from log4j, but you can use the standard Java Logger. The output should be similar, maybe a bit less. But I'm sure it can be configured.
Call e.printStackTrace(System.out);. Or, if you need it for debugging only, you can separate the process' output and error from the command line: .... 1>output.log 2>error.log
What's the easiest way to print a stacktrace from a debugging printout? Often during testing you would like to know the callstack leading up to the situation provoking a debug message.
If you're using log4j
Exception e = new Exception();
log.error("error here", e);
will print the stacktrace to your log.
Thread.dumpStack();
If you want to save the stack trace into a String you can do this;
String exception = "";
for (StackTraceElement element : e.getStackTrace())
exception += element.toString() + "\n";
Where e is, obviously, an exception.
Besides, it sounds very weird to autogenerate an own Exception just to find get a stack trace for a debug. Get Eclipse and use it's debug mode, it's really awesome.
Just creating an arbitrary exception does the trick for me:
System.out.println("Oops, the bad thing happened");
new IllegalStateException().printStackTrace();
As well as what #jjnguy said, if you don't have an exception, you can also call Thread.getStackTrace().
You should be catching the exception in a try-catch block.
e.getStackTrace();
That returns StackTraceElement[] that you can then interpret.
Also:
e.printStackTrace()
will...print the stacktrace.
To simply print the current stack trace to stderr, you can call:
Thread.dumpStack();
which itself just calls:
new Exception("Stack trace").printStackTrace();
To output to stdout rather than stderr, pass System.out to printStackTrace():
new Exception("Stack trace").printStackTrace(System.out);
Just because I needed it myself:
As inspired by answer How do I find the caller of a method using stacktrace or reflection? , you can retrieve the call stack using
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace()
Then you process and print/log whatever you are interested in. More work than using Thread.dumpStack(), but more flexible.