Logging method for thrown exception - java

I have methods that are defined as...
public static void myMethod throws IOException ....
how can I use the Logger class to log the exception that is thrown to a file say named "test.log". I've heard of using logger.throwing... but it doesn't seem to work. Could anyone give me a step by step tip on how to do this? I just basically need to log the exception that is thrown (I didn't use try catches). Thank you so much!

You'll need to add a catch clause. Below is a start for using the java.util.logging.Logger. Note that many projects use an Apache logger which is a bit more powerful and more complicated. Let's say you have a class com.myCompany.Foo that reads some file stuff
typically, at the start of the class in the static field declarations you will have
private static final Logger LOGGER = Logger.getLogger("com.myCompany.Foo");
then, when you have a method that throws exceptions (this is a stupid method!)
int readFirstCharOfFile(File f) throws IOException {
FileReader reader = null;
try {
reader = new FileReader(f);
return reader.read();
}
catch (IOException ioe) {
// You have a lot of possibilities here, but this seems most reasonable
LOGGER.log(Level.SEVERE, ioe.getMessage(), ioe);
// whether you rethrow the Exception "depends" on the contract, but, in our case
// the method declaration says that we do, so we do.
throw ioe;
}
finally {
if (reader != null)
reader.close();
}
}
The harder part is configuring the Logger to write where you want. IIRC, by default it goes to standard error. There is a lot of "magic" there that I never fully understood so I couldn't explain all the intricacies.
You can Google to get info, here are a couple useful links I found. link1 and link2

If you want a more automatic approach than the one given by user949300, you could take a look at Aspect-Oriented Programming (AOP), which allows you to do exception logging for all methods with just a little bit of code. Just google for aspectj log exceptions or java aop log exceptions.
See also question Audit Java: system to detect exceptions thrown / caught (aop?)

Try to use jcabi-aspects and its #LogException annotation:
public class Resource {
#LogExceptions
public String load(URL url) {
return url.openConnection().getContent();
}
}

Related

Java: Testing if an exception is caught within a larger system

I know there are a number of questions on this topic, but all of them seem to assume one of two things:
You just want to test if an exception was thrown and not caught,
You should test the function that is inside of the try block
directly
I'm not sure how I can apply those options to this case. I have a small try/catch block, like so:
try {
o.getDataContainer().build(...);
o2.setDataContainer(o.getDataContainer());
} catch (final Exception e) {
LOGGER.error("Data set failed", e);
}
As you can see, if o.getDataContainer() returns null, an exception would be triggered. However, that exception is then caught, and the test tool considers it a successful test. Is it possible to test that the exception occurred without changing the code?
I ask because our logging system triggers a trouble ticket if it picks up an exception that is caught and logged. Since it is common human error to forget to guard something like this, I would like to write UTs that can test if an exception was triggered and caught. I can't remove the whole-program protection provided by the catch block, but the error would also cause a degradation of the user experience, since the data isn't being passed along. (I work in a place where minutes of site downtime equal millions of dollars lost.)
In other words: The exception is an error, and we want to log it and investigate it, but in case this manages to trigger on prod, we don't want to risk the whole site going down.
Note: This try/catch sits inside a much larger function with many such try/catch blocks. One could easily argue bad overall design, but fixing it is not an option (without a huge amount of free dev time, at least).
Update: As the task at hand does not allow me to spend a great deal of time on this, I went with a very simple generic test that would fail if the guard and catch were both removed so that I could move on. But, I'm leaving the question unanswered for now in hopes of continuing conversation. I would love to be able to write a simple UT for each new feature that fails if any exceptions are triggered and caught.
Ignoring the issues with this code (Sometimes you've gotta put lipstick on a pig, I guess), this is how I might handle the situation.
I'd use Mockito and mock o2, then use an Answer to ensure the method is invoked.
A test might look like this:
#RunWith(MockitoJUnitRunner.class)
public class TestClass{
#Mock
O2 o2;
#Mock
O1 o1;
boolean exceptionThrown = false;
#Test
public void test(){
Mockito.doAnswer(new Answer<Void>(){
public Void answer(InvocationOnMock invocation) throws Throwable {
exceptionThrown = true;
throw new RuntimeException("some message");
}
}).when(o2).setDataContainer(DataContainer.class);
}
}
Essentially, you can Mock out o2 in your example, and force the exception.
If this doesn't quite do what you want, you may need to mock LOGGER and verify that it's invoked with LOGGER.error("some message");. Unfortunately, mocking statics is not at all elegant, but it can be done with PowerMock.
You could add a custom handler to LOGGER that just throws when an error is logged. For java.util.logging you could do something like:
LOGGER.addHandler(new Handler() {
public void publish(LogRecord record) {
if ("Data set failed".equals(record.getMessage())) {
throw new RuntimeException(record.getThrown());
}
}
public void flush() {}
public void close() throws SecurityException {}
});
I think log4j calls it "Appender," but the same principle should work. See How to create a own Appender in log4j? or How to Create a Custom Appender in log4j2?

Is disabling Checked Exceptions in Java possible?

I was reading an article about checked and unchecked Exceptions in Java and found this article/link:
https://projectlombok.org/disableCheckedExceptions.html
According to the article it's just a hack developed for javac.
Consider the code snippet below:
import java.io.*;
class Example
{
public static void main(String args[]) throws IOException
{
FileInputStream fis = null;
fis = new FileInputStream("myfile.txt");
int k;
while(( k = fis.read() ) != -1)
{
System.out.print((char)k);
}
fis.close();
}
}
Here I have to write public static void main(String args[]) throws IOException
because I am trying to open a file. Here "throws" clause is a must. Without it I will get an error. What if I am sure about the Existance of the file I am opening. i.e.myfile.txt in the mentioned location. At some point one can feel that few Checked Exceptions are not required for the code.
Is there any facility provided by Java to disable checked Exceptions according to the need?
Even after doing so much research I could not find a proper answer for it.
Is there any facility provided by Java to disable checked Exceptions according to the need?
No official facilities, but there are workarounds one can use when needed:
First, since there are both checked and unchecked exceptions in java, using unchecked exceptions might be an option. All exceptions which derive from RuntimeException are unchecked:
RuntimeException is the superclass of those
exceptions that can be thrown during the normal operation of the
Java Virtual Machine.
A method is not required to declare in its throws
clause any subclasses of RuntimeException that might
be thrown during the execution of the method but not caught.
Interesting read here, here.
Then there is type erasure which allows to throw a checked exception without declaring it.
This is what project lombok uses for #SneakyThrows
import lombok.SneakyThrows;
public class SneakyThrowsExample implements Runnable {
#SneakyThrows(UnsupportedEncodingException.class)
public String utf8ToString(byte[] bytes) {
return new String(bytes, "UTF-8");
}
#SneakyThrows
public void run() {
throw new Throwable();
}
}
Use with caution:
Be aware that it is impossible to catch sneakily thrown checked types directly, as javac will not let you write a catch block for an exception type that no method call in the try body declares as thrown.
And lastly it's only the compiler which cares about checked exceptions, it's not part of the jvm at all. Once you're past the compiler stage anything is possible. So writing bytecode directly or using a version of javac with checked exceptions disabled completely bypasses them.
Other than hacking the compiler there is no option to disable checked exceptions I know of. Best you can do is catch the checked exception and rethrow it within a runtime exception if you don't want to force the client code to handle the checked exception.

relax exception catch necessity

Is there a possibility in Java to get rid of the necessity to catch non-RuntimeException exceptions? Maybe compiler flags?
I know the reason why the catching is promoted, but want to do simple and straight tools that enforce their requirements. So if something can went wrong I don't like to catch up but exit the application, crashing with a meaningful exception. Usually this ends up like:
try {
connection.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
which introduces 4 lines of code mess, and introduces the wrapping RuntimeException mess on error output. Sometimes it even motivate people to wrap large try ... catch (Throwable ..) blocks around anything, which is the likely cause for our beloved 'Unknown error occured' alert boxes...
you can use throws keyword with method prototype to avoid try-catch block. which eventually throws the exception to JVM's Default Exception handler which halts the application if no catch block's are specified in your code to handle the exception raised.
Crashing the application at the first sight of an exception is very bad practice. Especially when some work is unsaved and the application is using some resources that needs to be freed and cleaned before the application terminates execution. Some very popular software used to do that... and instead of "fixing" the issue, they introduced a data recoverability features on application restart. However the trick, this is not good software engineering.
At the very least, your application should not crash on the first exception/error encountered, but recover with a meaningful message. It is being lazy to just wrap everything in a RuntimeException (or even Throwable) and, especially, not do anything with it.
Java does not support flags of any kind because there are 1) a workaround, and 2) better ways to handle this situation. For example :
1. Handle the exception in the calling method
You can add the throws keyword in your method declaration, up to your static public void main method, which, if not handling the exception, will eventually crash the application with a stacktrace.
class Foo {
public void someMethod(....) throws IllegalArgumentException, IOException {
...
}
static public void main(String...args) throws Throwable {
new Foo().someMethod();
}
}
This method does not offer any means of recoverability and will probably make your user unhappy (with a big meaningless stachtrace if they ran the application from a console, or just nothing at all if they launched it from a shortcut or GUI). Also, if you have some acquired resources, you will not be able to clean them when an exception occurs. At the very least, your main should catch (Throwable e) and output something before throwing the exception above. Something like :
class Foo {
public void someMethod(....) throws IllegalArgumentException, IOException {
...
}
static public void main(String...args) {
try {
new Foo().someMethod();
} catch (...) {
// output or log exception here and, optionally, cleanup and exit
}
}
}
** EDIT **
Consider this scenario : a program is initializing some resource for processing some data, then some runtime exception (or error) occurs during processing, the application crash, but the resources are not released or freed. In Java, however, one could do this
public E doSomething() throws RuntimeException {
// declare a bunch of resources
try {
// process resources with unchecked exceptions
} finally {
// free resources
}
// return some result
}
and cleanly exit the method on error or on success, perhaps even logging the runtime error for "posterity".
2. Log the error and return some meaningful value
Logging is a very good practice. You can show your user some message telling them that the operation could not be executed without crashing the whole thing, and giving you some traces of what and where the user were doing. A simplistic logging system could be :
class Foo {
static private final Logger LOG = Logger.getLogger(Foo.class.getName());
public boolean doSomethingImpl(...) {
boolean result = true;
try {
...
} catch (SomeException e) {
LOG.log(Level.SEVERE, "meaningful message why method could not do something!", e);
result = false;
}
return result;
}
public void doSomething() {
if (!doSomethingImpl(...)) {
// handle failure here
}
}
}
By default, the Logger will output everything to the err output stream, but you can add your own handlers :
// loggers are singletons, so you can retrieve any logger at anytime from
// anywhere, as long as you know the logger's name
Logger logger = Logger.getLogger(Foo.class.getName());
logger.setUseParentHandlers(false); // disable output to err
logger.addHandler(new MyHandler()); // MyHandler extends java.util.logging.Handler
Java already ships with some default logging handlers, one of which writes to file.
etc.
Is there a possibility in Java to get rid of the necessity to catch non-RuntimeException exceptions?
For a checked exception, you can chose between catching the exception and declaring it in the method header as thrown.
Maybe compiler flags?
No. There are no compiler flags to relax this. It is a fundamental part of the language design. Relaxing the checked exception rules via a compiler switch would cause serious library interoperability problems.
I don't think that there's any way around this for the JVM. Your best bet is to have your methods re-throw the exception, which gets rid of the "mess" in your code, and then have your main program throw Exception. This should propagate the error up to the top of your program.
Keep in mind, however, that the place where the exception actually happens is a much better place to let the user know what happened (i.e., exactly what it was doing when this particular IOException happened). You'll lose this resolution if all errors are simply propagated up to the top level.
You do have the ability to throw your exceptions up a level. Here's an example
public class Foo {
public Foo() {
super();
}
public void disconnect(connection) throws IOException {
connection.close();
}
}
Use "Throws" to avoid the error..but it will not be good programimg practice

Could you suggest me a pattern to log exceptions during java application lifecycle?

I want to use the simple java.util.logging.* package to log exceptions. Any suggestions, links, articles to do this in a basic but elegant way?
I should implement it in a Java EE application.
I was thinking to a singleton class... what do you think?
The following doesn't handle the case of logging all exceptions automatically but might get you closer. At my current company we extended Exception with a CompanyException that supported a list of callbacks. Something like:
public abstract class CompanyException extends Exception {
private static final List<ExceptionCallback> callBacks =
new ArrayList<ExceptionCallback>();
public CompanyException(String message) {
super(message);
invokeCallbacks();
}
// register class to be called whenever exception is constructed
public static void registerCallback(ExceptionCallback callback) {
// we expect the registers to be done long before the first exception thrown
List<ExceptionCallback> newCallbacks = new ArrayList<ExceptionCallback>();
newCallBacks.addAll(callBacks);
newCallbacks.add(callback);
callBacks = newCallBacks;
}
private void invokeCallbacks() {
for (ExceptionCallback callBack : callBacks) {
try {
callBack.exceptionConstructed(this);
} catch (Throwable th) {
// ignore it because we can't go recursive
}
}
}
}
The callback was a simple interface:
public interface ExceptionCallback {
public void exceptionConstructed(Exception exception);
}
Then all of our internal exceptions would throw these or rethrow/wrap external exceptions. We then would register a logging class which could log exceptions using log4j or our internal logging mechanisms. Obviously the exception could do the logging itself but we wanted the separation. Our logger had a dedicated thread to do it in the background and send it to the central logging server. You need to be very careful about recursion if you throw while you are logging.
You can take a look at Base 22's logging suggestions, they're pretty basic but they cover a basic set of standard logging functionality.
I discourage the use of a Singleton, as with a modern logging framework you don't need them.

How can I detect when an Exception's been thrown globally in Java?

How can I detect when an Exception has been thrown anywhere in my application?
I'm try to auto-magically send myself an email whenever an exception is thrown anywhere in my Java Desktop Application. I figure this way I can be more proactive.
I know I could just explicitly log and notify myself whenever an exception occurs, but I'd have to do it everywhere and I might(more likely will) miss a couple.
Any suggestions?
You probobly don't want to mail on any exception. There are lots of code in the JDK that actaully depend on exceptions to work normally. What I presume you are more inerested in are uncaught exceptions. If you are catching the exceptions you should handle notifications there.
In a desktop app there are two places to worry about this, in the event-dispatch-thread (EDT) and outside of the EDT. Globaly you can register a class implementing java.util.Thread.UncaughtExceptionHandler and register it via java.util.Thread.setDefaultUncaughtExceptionHandler. This will get called if an exception winds down to the bottom of the stack and the thread hasn't had a handler set on the current thread instance on the thread or the ThreadGroup.
The EDT has a different hook for handling exceptions. A system property 'sun.awt.exception.handler' needs to be registerd with the Fully Qualified Class Name of a class with a zero argument constructor. This class needs an instance method handle(Throwable) that does your work. The return type doesn't matter, and since a new instance is created every time, don't count on keeping state.
So if you don't care what thread the exception occurred in a sample may look like this:
class ExceptionHandler implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
handle(e);
}
public void handle(Throwable throwable) {
try {
// insert your e-mail code here
} catch (Throwable t) {
// don't let the exception get thrown out, will cause infinite looping!
}
}
public static void registerExceptionHandler() {
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());
System.setProperty("sun.awt.exception.handler", ExceptionHandler.class.getName());
}
}
Add this class into some random package, and then call the registerExceptionHandler method and you should be ready to go.
The new debugging hooks in Java 1.5 let you do this. It enables e.g. "break on any exception" in debuggers.
Here's the specific Javadoc you need.
Check out Thread.UncaughtExceptionHandler. You can set it per thread or a default one for the entire VM.
This would at least help you catch the ones you miss.
If you're using a web framework such as Spring then you can delegate in your web.xml to a page and then use the controller to send the email. For example:
In web.xml:
<error-page>
<error-code>500</error-code>
<location>/error/500.htm</location>
</error-page>
Then define /error/500.htm as a controller. You can access the exception from the parameter javax.servlet.error.exception:
Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception");
If you're just running a regular Java program, then I would imagine you're stuck with public static void main(String[] args) { try { ... } catch (Exception e) {} }
If you are using java 1.3/1.4, Thread.UncaughtExceptionHandler is not available.
In this case you can use a solution based on AOP to trigger some code when an exception is thrown. Spring and/or aspectJ might be helpful.
In my current project I faced the similar requirement regarding the errors detection. For this purpose I have applied the following approach: I use log4j for logging across my app, and everywhere, where the exception is caught I do the standard thing: log.error("Error's description goes here", e);, where e is the Exception being thrown (see log4j documentation for details regarding the initialization of the "log").
In order to detect the error, I use my own Appender, which extends the log4j AppenderSkeleton class:
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
public class ErrorsDetectingAppender extends AppenderSkeleton {
private static boolean errorsOccured = false;
public static boolean errorsOccured() {
return errorsOccured;
}
public ErrorsDetectingAppender() {
super();
}
#Override
public void close() {
// TODO Auto-generated method stub
}
#Override
public boolean requiresLayout() {
return false;
}
#Override
protected void append(LoggingEvent event) {
if (event.getLevel().toString().toLowerCase().equals("error")) {
System.out.println("-----------------Errors detected");
this.errorsOccured = true;
}
}
}
The log4j configuration file has to just contain a definition of the new appender and its attachement to the selected logger (root in my case):
log4j.rootLogger = OTHER_APPENDERS, ED
log4j.appender.ED=com.your.package.ErrorsDetectingAppender
You can either call the errorsOccured() method of the ErrorsDetectingAppender at some significant point in your programs's execution flow or react immidiately by adding functionality to the if block in the append() method. This approach is consistent with the semantics: things that you consider errors and log them as such, are detected. If you will later consider selected errors not so important, you just change the logging level to log.warn() and report will not be sent.
In this case I think your best bet might be to write a custom classloader to handle all classloading in your application, and whenever an exception class is requested you return a class that wraps the requested exception class. This wrapper calls through to the wrapped exception but also logs the exception event.
I assume you don't mean any Exception but rather any uncaught Exception.
If this is the case this article on the Sun Website has some ideas. You need to wrap your top level method in a try-catch block and also do some extra work to handle other Threads.
Sending an email may not be possible if you are getting a runtime exception like OutOfMemoryError or StackOverflow. Most likely you will have to spawn another process and catch any exceptions thrown by it (with the various techniques mentioned above).
There is simply no good reason to be informed of every thrown exception. I guess you are assuming that a thrown exception indicates a "problem" that your "need" to know about. But this is wrong. If an exception is thrown, caught and handled, all is well. The only thing you need to be worried about is an exception that is thrown but not handled (not caught). But you can do that in a try...catch clause yourself.

Categories