What are the best practice of making code error stable? - java

I need make some code super stable and make sure all exceptions thrown within a block don't stop the code execution.
For now i have the following solution:
iterated.map(it -> {
try {
handleElement(it);
} catch (Exception e) {
handleError(e);
}
});
But from the other side i feel like there should be more elegant way to do it. Please help me to find it.

Well that's indeed how to call exceptions, but it's more important how to deal with these occurrences. An Exception should be thrown when the app experiences something which it could not expect. Just catching all exceptions will
Not make your code more stable, it just doesn't throw exceptions higher up
Leave errors as-is, and they will still be thrown (you probably want this)
Remove exceptions which you might want to have logged
Keep in mind what is a REAL exception for your app. Here are some examples:
You have a connection to a backend, which is unstable. You knew this, and made the app possible to reconnect and/or postpone the actions, or whatever in order for the app that this backend is in fact unstable:
This is NO exception, just log a message if needed.
The client misentered some information
NO exception, this happens all the time, the app should cope with that
After some code update you have a problem even setting up the connection
EXCEPTION: log it and fix the problem!

There is nothing wrong with you code and probably I would keep as is but if you like you can have a function that handles another function and catches the exceptions:
public class ExceptionCatcher<T, R> implements Function<T, R> {
public final Function<T, R> function;
public final Function<Exception, R> exceptionHandler;
public ExceptionCatcher(Function<T, R> function, Function<Exception, R> exceptionHandler) {
this.function = function;
this.exceptionHandler = exceptionHandler;
}
#Override
public R apply(T o) {
try {
return function.apply(o);
}catch (Exception e){
return exceptionHandler.apply(e);
}
}
};
and your code will look like:
ExceptionCatcher ex = new ExceptionCatcher(this::handleElement, this::handleError);
iterated.map(ex);
This is just an example; probably instead of a simple Consumer you want a BiFunction and map to a default value based on the exception and on the failing onject. Or return null and filter null after this. It depends a lot on what you want to achieve

Related

Throwing custom exceptions in a functional interface

I am writing a program that consumes some data from a RabbitMQ API, via the java.function.Consumer functional interface. In my subclass that implements this interface, I have 3 potential exceptions:
public interface MyMessageHandler extends Consumer<MyMessage> {}
public class SpecificMessageHandler implements MyMessageHandler {
#Override
public void accept(IncomingMessage incomingMessage) {
if(incomingMessage.getTime() < 1000) {
throw new InvalidTimeException("message"); //Custom exception extends RuntimeException
}
if(incomingMessageAlreadyExists) {
throw new DuplicateMessageException("message"); //Custom exception extends RuntimeException
}
try {
ObjectMapper.reader.readValue(incomingMessage.getJson()) // Throws IOEXception
} catch(IOException e) {
throw new CustomIOException("message"); //Custom exceptin extends RuntimeException
}
// If all is well, carry on with rest of function
}
}
I am having to take this route because you can't seem to throw regular exceptions in a functional interface, it has to be a runtime exception.
I am throwing the exceptions at this level of the stack, as I want to implement the actual handling behaviour higher up the stack, due to the fact I will have many message handlers that will be handled in the same way, therefore it's easier to implement that handling behaviour once higher up, rather than in every single handler class.
This functionally works, however feels like bad design. Is there a more elegant way to implement this? Note, I can't switch from a functional interface to something else, as i'm working with legacy code (not ideal, but that's how the world is some times!)
I am having to take this route because you can't seem to throw regular
exceptions in a functional interface, it has to be a runtime
exception.
This is incorrect. You can't throw checked exceptions in a java.function.Consumer specifically, because its signature
void accept(T t);
doesn't declare any.
The following functional interface is perfectly acceptable, and can throw certain checked exceptions.
public interface MyMessageHandler {
void accept(IncomingMessage incomingMessage) throws IOException;
}
MyMessageHandler handler = (msg) -> {
throw new IOException(); // Valid
};
If you wanted something more generic, you could declare something like
public interface ThrowableConsumer<T> {
void accept(T t) throws Exception;
}
interface MyMessageHandler extends ThrowableConsumer<MyMessage> {}
I am throwing the exceptions at this level of the stack, as I want to
implement the actual handling behaviour higher up the stack
You could use Lombok's #SneakyThrows to effectively convert a checked exception into an unchecked one. A hack, but it works.
class SpecificMessageHandler implements MyMessageHandler {
#Override
#SneakyThrows
public void accept(IncomingMessage incomingMessage) {
// Doesn't matter that it's checked and j.f.Consumer doesn't declare it
throw new IOException();
}
}
However I highly doubt that your employer will allow you to do hacks like this if you're not permitted to change an interface.
This functionally works, however feels like bad design
Why? There's a huge class of people who believe that checked exceptions were a mistake to begin with. There's nothing wrong with runtime exceptions.
Note, I can't switch from a functional interface to something else, as
i'm working with legacy code
People throw this word around a lot. Java 8 came out 8 years ago. Your code can't be that old. Usually when people say "I can't change X", what they mean is that they don't feel comfortable changing it, for whatever reason. If you're living in fear of your software, find a way to change that.

Creating and use a List of Classes List<Class<?>>

In JUnit5s using handleTestExecutionException method, provided by TestExecutionExceptionHandler, which is called whenever a test throws an exception that is not caught by the code.
I am trying to detect if we have had a crash on one of our hardware devices.
These crashes can be detected in several ways, as we have many ways of communicating to with our different systems (Rest, Telnet, SSH, WebSocket, SOAP, etc) which all throw their own type of errors.
So, instead of having a massive if statement that checks each of the throwable was an instanceof RestException, TelnetException...,
I was hoping to make a list of the Classes and just loop over this list to see if the thrown error is in that list.
This seems like it would be more maintainable and easier to read than a giant if statement.
#Override
public void handleTestExecutionException(ExtensionContext extensionContext, Throwable throwable) throws Throwable {
List<Class<? extends Throwable>> crashErrors = Arrays.asList(NotFoundException.class, BadGatewayException.class, SocketTimeoutException.class, ConnectException.class, ...);
for(Class<? extends Throwable> error : crashErrors){
if(throwable instanceof error) {
//process the crash
break;
}
}
}
Was hoping to iterate over the list to determine if the system had crashed.
Is there a way to do it this way, or would it just be better to have an if statement with something like 20 or statements?
Take a look at the methods of Class. There you can find isInstance ;)

How to centralize exception handling in multiple methods of an API

This is a plain Java 8+ question, no frameworks used.
We are producing an API for a higher layer which deals with the presentation layer among other activities. We have and interface agreed with the invoker, so they are happy to receive some particular exceptions we throw.
At the same time, we are also using other APIs under the same agreement, so we can do stuff by ourselves and throw exceptions or we can invoke other APIs which throw the agreed exceptions.
Currently, we do nothing with the exceptions thrown by the APIs we are invoking.
Thing is, we are the best positioned in this infrastructure to deal with intermediate activities while exceptions are thrown, so we need to capture both, our exceptions and the exceptions provided by those we are invoking; basically reporting the issue, raising system controls, etc, and then re-throw the original exception so the top layer keeps as it is now.
We have around 300 methods in the entry point class of our API:
public void method1 (arguments for method 1) {
...
}
...
public void method300 (arguments for method 300) {
...
}
I clearly understand that I can create a method to centralise the actions to be taken in the exception management, something like:
public void myExceptionHandler (Exception e) {
if (e instanceOf X) {
} else if ...
...
throw particularExceptionAccordingTheCase
}
But I'd also avoid modifying those 300 methods.
Any idea how to inject a try-catch in those 300 methods to send the Exception to myExceptionHandler without really adding a try-catch in each of them?
Any comments and ideas are much appreciated!
----------- After mprev0 suggestion -------------------------------
I tried this approach. It really catches the exception and so on, but I can't re-trow an Exception: I'm forced to catch it, but this goes against the requirement of re-sending the exception back to the top layer.
While I can throw an Error, I got a compiler error at line throw new FileNotFoundException();
public class myExceptionHandler implements Thread.UncaughtExceptionHandler {
#Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("gotcha!");
if (e instanceof java.lang.Error) {
System.out.println("AAT-CORE: Fatal Error");
throw new java.lang.Error(e.getCause());
} else if (e instanceof java.lang.Exception) {
System.out.println("AAT-CORE: Exception Error");
throw new FileNotFoundException();
}
}
}
Any ideas?
------------ After some more digging, fixed with a decorator pattern -------
Previous class implementation does not work, as I can't change the signature of the method and I need to re-throw the java.lang.Exception.
Using a decorator and handling the interface there makes the trick.
As a summary:
Top layer class:
public class TopLayer {
public static void main (String[] args) {
MiddleLayer m = new MiddleLayer();
m.method1();
}
}
Bottom layer class contains specific APIs and some implementation, the only interesting thing is that it contains java.lang.Exceptions uncontrolled, expecting the top layer to do this job. But, we are working in the middle and we will do this job:
public class MiddleLayer extends BottomLayer {
public MiddleLayer () {
final UncaughtExceptionHandler subclass = Thread.currentThread().getUncaughtExceptionHandler();
Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
System.out.println("gotcha2!");
// carry on with prior flow
subclass.uncaughtException(thread, ex);
}
});
}
}
In this way, I can get the system.out and the java.lang.Exception is propagated to the Top Layer.
Decorator inspiration came from here: Rethrow UncaughtExceptionHandler Exception after Logging It
Additional comments are welcome!
You can solve this by implementing the java.lang.Thread.UncaughtExceptionHandler interface:
public class MyExceptionHandler implements Thread.UncaughtExceptionHandler {
#Overrides
public void uncaughtException(Thread t, Throwable e) {
if (e instanceOf X) {
} else if ...
...
throw particularExceptionAccordingTheCase
}
}
Then you associate it to all threads as follows:
Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler())
This will configure the exception handler to handle all uncaught exceptions in all threads of your application.
Note that this will only work for exceptions that aren't yet explicitly handled somewhere in your code and if there is no other handler configured for some particular thread (the uncaught exception handler can also be set for some specific thread).
EDIT: As discovered by #JBC, the above approach will not work for checked exceptions since we are forced to catch them explicitly in our uncaughtException method (note that we cannot add a throws clause to an overridden method). While it will work without problems if we only want to re-throw subtypes of RuntimeException and Error, there is a little adaptation needed if we want to make it work - you can find it explained in #JBC's question.
As you can see in the question updates, the final solution is a combination of two different approaches, in one side, having the mprev0 approach of implementing the java.lang.Thread.UncaughtExceptionHandler and, on top of this, adding a Decoration pattern to be able to re-throw a run-time exception.
There were no additional approaches so far, so I'm closing the question and bring this as the most complete response.
More information about UncaughtExceptionHandler can be found in the Java documentation, but as always, is short on examples, and here:
Advanced exception handling
Thread.UncaughtExceptionHandler Example
More information on Decorator pattern usage, can be found here:
Decorator Design Pattern in Java
Design Patterns - Decorator Pattern
And how to use to manipulate exceptions here:
Rethrow UncaughtExceptionHandler Exception after Logging It
You could also create a proxy API on top of your current API, have an invocation handler method in the proxy and put this method in a try catch block.
https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html
https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html

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?

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

Categories