What is the best practice to follow when you need to throw an exception which was not defined in an interface that you are implementing?
Here is an example:
public interface Reader
{
public abstract void read() throws IOException;
}
public class CarrotReader implements Reader
{
public void read() throws IOException {}
}
public class CupcakeReader implements Reader
{
public void read() throws IOException, CupcakeException {}
}
In this case, you have a specific exception that occurs when reading cupcakes, so you want to throw an exception related to this. However, Reader doesn't define this type of exception in its interface, so what do you do? Furthermore, it doesn't make sense to add CupcakeException to the throws clause in the Reader interface, because this type of exception is specific to CupcakeReader. One way around this is to have Reader define read such that it throws some parent type, like Exception, but then you lose the context for the exception. What should you do in this situation? Thanks!
Another interesting situation that has been brought up involves an interface over which you have no control. In this case, what is the best way to indicate that a problem has occurred?
For illustrative purposes, here is another example:
public interface Reader
{
public abstract void read();
}
public class CupcakeReader implements Reader
{
public void read() throws CupcakeException {}
}
In this case, you cannot change Reader, but you want to indicate that a problem has occurred in CupcakeReader's read method.
You may have to create an exception of the expected type instead.
... catch(CupcakeException e) {
throw new IOException("The sky is falling", e);
}
Use something called ReaderException that will serve as the root interface of your exception hierarchy. ReaderException will also provides a link to other exceptions that get thrown due to lower level exceptions.
Exception is part of the interface. Define a generic parent for all your exceptions in the interface if you can redefine the interface.
You can also make CupcakeException a child of IOException.
Just don't use checked exceptions.
The example you showed is one of the reasons checked exceptions are bad.
The main reason though is that the user of your cupcake reader will have to handle your exception regardless of whether he is interested in it or not.
So instead of:
Value value = reader.read();
You are forcing him to do this:
Value value = null;
try {
value = reader.read();
} catch (Exception e) {
// now what??
}
value.doSomething(); // potential NPE here
Think which one is better, more readable and less error prone and just stop using checked exceptions.
EDIT:
I am surprised with the negative rating. Are there people who still think that checked exceptions are great? If so here are some references why you shouldn't use checked exceptions:
No modern framework uses checked exceptions (Spring, EJB3 etc)
Article with code examples here
StackOverflow topic
Effective Java (sections 58 and 59) - here
Perhaps you could make an abstract ReaderSpecificException class, put it in the Interface, and
subclass CupcakeException from this abstract class.
If you create a higher abstract exception that works as a base class for CupCakeException you don't bind the Reader Interface to a specific implementation like you would be doing if you added the CupCakeException to the Reader interface.
If you don't let one Exception inherit from another there is a constructor in the exception class that takes a throwable as second argument like Thorbjørn Ravn Andersen allready showed in his short code example. The enables you to generate a more abstract exception and every part of your code that needs to know more then just "there is an error" can look for the cause of the higher exception.
Related
Let's say I have a class as below, as the class name suggests, this class doesn't allow auto commit.
So my question is that if it is better to leave it like below (empty body, maybe add some logging #WARN/ERROR level) or to throw UnsupportedOperationException?
public class NoAutoCommitConnection implements java.sql.Connection {
public void setAutoCommit(boolean autoCommit) throws SQLException {
}
}
I would actually go with if(autoCommit) { throw new UnsupportedOperationException(); }, since it clearly communicates that auto commiting is not supported, but won't fail setAutoCommit(false) calls.
Not implementing the method or rather it's intention breaks the contract of the interface.
I think the least you can do in such a situation is to throw an exception at runtime.
In a flow I've designed, I have a Validation component with a custom validator that references a class, DataValidator, implementing the mule Validator interface. In the DataValidator, I validate several properties and would like to throw different kinds of exceptions (possibly custom exceptions, created by me) for each one. Is this possible?
My understanding is that, by specifying the exceptionClass, the Validation component will only throw exceptions of that class.
There's the option to use an ExceptionFactory instead of an exceptionClass.
Does using it allows throwing several types of exception? If so, how can I use it? I checked this blog
post, but didn't understand it well enough.
In the case that none of this is possible, is there any way I can get the ValidationResult message in the custom validator component, so that I can use it in the message?
Yes you can throw several types of exceptions. As you mentioned, you'll have to implement the DataValidator and ExceptionFactory interface and configure your component to use them.
With Studio, choose "Use Exception Factory Config" and specify the full class name you want to use. With XML, specify the exception-factory you implemented in your validation-config. (You can also configure a Spring Bean and reference it):
<validation:config name="Validation_Configuration" doc:name="Validation Configuration">
<validation:exception-factory class="com.mycomp.validation.MyExceptionFactory"/>
</validation:config>
In your flow configure acustom-validator and reference your configuration with exception factory, your validator implementation and the type of exception you want to throw with exceptionClass. To be able to throw any kind of Exception, specify java.lang.Exception or a class from which the custom exceptions you'll want to use can inherit:
<flow name="validation-exceptionFlow">
...
<validation:custom-validator
config-ref="Validation_Configuration"
class="com.mycomp.validation.MyValidator"
exceptionClass="java.lang.Exception"
doc:name="Validation" />
...
</flow>
Depending on your need you may want to specify exceptionClass differently, the idea being that your actual exceptions should extend it.
Yout ExceptionFactory implementation is then up to you. You can return whatever exception you want... For example:
public class MyExceptionFactory implements ExceptionFactory{
#Override
public <T extends Exception> T createException(ValidationResult result, Class<T> exceptionClass, MuleEvent event) {
return (T) createException(result, exceptionClass.getCanonicalName(), event);
}
#Override
public Exception createException(ValidationResult result, String exceptionClassName, MuleEvent event) {
//...
//some logic to identify which kind of exception you want to throw
//from result and event
//...
if(something) {
return new SomeException("Something happened");
} else if (somethingElse) {
return new AnotherException("I am en error...");
} else {
return new BananaException("Ook");
}
}
}
It appears the interface has two methods, one returning a generic and the other a plain Exception. Not knowing the specific usage of your ExceptionFactory I won't be able to provide much guidance, but be aware that Mule may call any of these methods, and the doc provides some requirements:
The above interface receives the Event that was rejected by the
validation and the validator that raised the error. This method is
intended to return the exception to be thrown but not to throw it.
Implementations of this interface should never throw exceptions. They
should also be thread-safe and have a public default constructor. See
Also
I would like to customize java exceptions class by adding an attribute to them. It could be as simple as the following attribute:
boolean isThisStupid;
void setIsThisStupid(boolean iValue);
boolean getIsThisStupid();
Every time I would instantiate an exception, like a NullPointerException, or an IllegalArgumentException, it would contains this attribute.
Since I do not have the source code of Java, I cannot of course edit the Exception base class.
I've considered using the decorator pattern, using an "ExceptionDecorator" class implementing an IException interface, however, doing this I would lose the initial exception type, which I do not want. For example for:
IException mException = new ExceptionDecorator( new NullPointerException() );
I would get:
mException instanceof ExceptionDecorator; //true
mException instanceof NullPointerException; //false
I want my custom exception to be an instance of NullPointerException.
This is totally generic, I want this to be working with any subclass of Exception.
Is this even possible ? If yes, maybe there's a pattern which could help me and I don't know about ?
I've done my best to be clear, if I'm not, please ask for more details and I will rephrase the initial topic.
Thanks
I want my custom exception to be an instance of NullPointerException.
It is not possible at compile time. To do what you want, you should create dynamically your exception class at runtime with Javasist for example.
Otherwise for static typing, you could use decorators. Decorators have to use the same interface/class than decorated objects. It is the base of the decorator.
In your case, the base class cannot be a new interface you create since you cannot change the code of existing exceptions. So the common abstract class between decorator and decorated objects is Exception.
You could have a decorator like that :
public class DecoratorException extends Exception{
private Exception decorated;
private boolean isStupid;
public DecoratorException(Exception exception){
this.decorated = exception;
}
public void setStupid(boolean iValue){
// TODO
}
public boolean getStupid{}{
// TODO
}
// get effective exception
public Exception getEffectiveException(){
return decorated;
}
// decorate the method you wish
// for example toString()
public String toString(){
return decorated.toString() + ", isStupid=" + isStupid);
}
}
The idea of Decorator is adding behavior to the decorated object.
In my example, I decorated the toString() method to display the new field with its value.
You can then rise an exception like that :
Exception e = new DecoratorException(new IllegalArgumentException());
e.setStupid(true);
throw e;
Thanks you all for your answers, it seems like nothing can really satisfy what I need. So I may just change my idea rather than forcing something that would turn awkward and not maintainable
I think your best bet here would be to continue with the decorator pattern here as you described, and instead of using instance of, create another method in your exception class (#containsInstanceOf or something) and using that in your code to check the contained type.
I think the only way to add the behavior you want would be to mess with the byte code like Lombok does, or by creating proxy objects. Both of those are pretty messy and it's probably easier to just use the decorator pattern and deal with the fact that instance of won't work.
For getting the exception class to extend NullPointer, do something like this:
public MyNewException extends NullPointerException
{
/*define methods and variables*/
}
For a class to work with any subclass of exception, you would have to define it as follows:
public MyNewException extends Exception
{
/*define stuff*/
}
Let me know if this is not what you want to be done.
Guice provides a way to bind to provider:
bind(A.class).toProvider(AProvider.class);
Although if my provider needs to throw an exception then it seems that CheckedProvider is a right base interface:
public interface ConfigCheckedProvider<T> extends CheckedProvider<T> {
T get() throws ConfigException;
}
public AProvider implements ConfigCheckedProvider<A> { ... }
But now some of my classes need instance of A to be injected. And this I can't change. But it looks like toProvider method doesn't accept CheckedProvider types.
How I can use providers based on CheckedProvider to inject instances not providers?
As you requested, I'm posting my comment as an answer.
If you have a class T and a checked provider TProvider extends CheckedProvider<T>, you cannot inject just T:
#Inject
SomeClass(T t) { // Won't work
...
}
as you would be able if you had used plain Provider<T>. This is done intentionally. Checked providers are needed when creation of an object may fail with a particular type of exception, and this failure must be handled by user code. Plain providers do not have such feature.
Provider<T> does not allow throwing checked exceptions from its get() method, and any unchecked exceptions it throws may be wrapped into a ProvisionException, so you cannot reliably catch your exception. Also, if you inject T directly and your provider's get() method fails, then you will get an error during the injection, which may lead to incomprehensible stacktraces (especially if you are not using Injectors directly) or even their absence.
Checked providers allow you to throw predeclared types of exceptions from your providers, and these exceptions are guaranteed to be passed as is to the code which calls get() on your checked provider. This way you can reliably catch them, but in return you lose an ability to inject objects which are created by the provider directly.
See this manual on throwing and checked providers for more background on what I just have written.
It's clear that what I'm asked for is intentionally not provided in guice. However the one might write his own checked provider which will implement Provider and therefore usable in toProvider bindings.
For example I have provided in question the following Checked Provider might make sense:
public abstract class MyCheckedProvider<T, E extends Exception>
implements Provider<T> {
public abstract T getChecked() throws E;
#Override
public T get() {
try {
return getChecked();
} catch (Exception e) {
throw new ProvisionException("Checked provider threw exception", e );
}
}
}
With this MyProvider the AProvider might look like:
public class AProvider extends MyCheckedProvider<A, ConfigException> {
#Override
public A getChecked() throws ConfigException {
...
}
}
bind(A.class).toProvider(AProvider.class);
All this works only if you want to throw ProvisionExceptions if something goes wrong in provider. For other logic MyProvider should obviously have other implmentation of get method...
First off, for anyone out there who abhors, detests and despises the instanceof operator, I understand your concerns with it, but am stuck using it. That's because I don't have the authority to completely refactor the way another development team set a project up, so unless I'm missing somethin here, I just don't see any way of avoiding it.
I have a Java POJO that cannot be changed, and allows you to set an Exception as one of its properties:
public class Message {
private Exception exception;
public void setException(Exception exc) {
this.exception = exc;
}
}
Again, I can't change this Message class.
I am writing an error handler method that gets passed a MessageContainer instances, and I need logic to do different things depending on what type of exception was set on the container's Message:
public class ErrorHandler {
public void handle(MessageContainer container) {
Message msg = container.getMessage();
Exception exc = msg.getException();
if(exc instanceof FizzException)
System.out.println("Do x");
else if(exc instanceof BuzzException)
System.out.println("Do y");
else
System.out.println("Do z");
}
}
Again, I can't change the fact that ErrorHandler#handle is passed a MessageContainer and not an injectable Message instance.
So, even though I really don't like to use instanceof, I don't see any other way of accomplishing this logic (but by all means, please make suggestions...as long as they don't involve making changes to Message, MessageContainer, or the handle(MessageContainer) method!).
But even with using instanceof, how does this code even work? Once you pull the Exception out of the Message, I don't think any of the instanceofs will fire, because its cast to an Exception, with no way to detect if it's BuzzException, FizzException, etc. What are my options here? Thanks in advance.
This code will work as expected. During runtime, instanceof statements will compare the actual type of exc, and not just assume this is only an Exception. If the only statement that worked was exc instanceof Exception, instanceof would be totally worthless :)
Another solution (which I would avoid to use) would be to compare fully qualified class names:
String fqcn = exc.getClass().getName();
if (fqcn.equals("com.foo.FizzException") {
// etc.
}
The cast to exception on
Exception exc = msg.getException();
does not erase the exception runtime type. It has merely cast it to a base type. The instanceof will still work. However, if your FizzException extends BuzzException, then you will need to do the instanceof checks in the other order. i.e. check for the most derived type first.
Otherwise, it will go into the base class check clause instead of the derived one.
It's not clear what you want. If the exceptions are all "given" and you can't change their implementations then you can use exception.getClass().getName() to get the class name and, maybe, look it up in a table or whatever to pick your course of action.
If you can change many of the exception implementations have them all implement an interface that provides a "functionality()" method or whatever. If an given Exception object is instanceof MyFunctionalityInterface then cast to MyFunctionalityInterface and call functionality() to have it return the info you need to guide your actions. Then use instanceof or getClass().getName() to manage the Exception classes you can't change.