subclass throw UnsupportedOperationException versus ignoring input parameter - java

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.

Related

Java, Mule - Throw different types of exceptions on one Validation component

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

Can implementations of Handler.publish() throw runtime exceptions?

I have a question about java.util.logging.Handler:
Is an implementation of this abstract method allowed to throw RuntimeExceptions, or should it always report to the error manager?
The documentation does not specify, but other methods in the class explicitly state what they can throw:
public abstract void publish(LogRecord record) Publish a LogRecord.
The logging request was made initially to a Logger object, which
initialized the LogRecord and forwarded it here.
The Handler is responsible for formatting the message, when and if
necessary. The formatting should include localization.
Parameters: record - description of the log event. A null record is
silently ignored and is not published
[Link: https://docs.oracle.com/javase/7/docs/api/java/util/logging/Handler.html#publish(java.util.logging.LogRecord)]
This is a case where the API spec doesn't always match the implementation. The unwritten rules from the source code seem to be:
Handling of a null record can be hostile or ignored. Subclasses of StreamHandler ignore null and the MemoryHandler is null hostile. The logger never passes null to publish and JDK-8216363: NullPointerException in java.util.logging.Handler#isLoggable makes it so null records are treated as ignored.
Any runtime exception thrown from isLoggable will escape the Handler. Which means any exception thrown from a filter escapes the publish method and is not trapped by the error manager. Notice how there is no enum ErrorManager.FILTER_FAILURE so that implies that the behavior is intentional.
Exceptions that the publish should not throw are enumerated in the ErrorManager documentation. Most cases are formatting and writing errors.
Really publish should delegate to the error manager to determine if publish throws exceptions or not. From the Handler.setErrorManager documentation:
The ErrorManager's "error" method will be invoked if any errors occur while using this Handler.
This implies that publish should obey the behavior of the error manager which by default doesn't throw.
If you want to get an exception through Handler.reportError you have to use a sneaky throw.
public class HostileErrorManager extends ErrorManager {
public HostileErrorManager() {
}
#Override
protected void reportError(String msg, Exception ex, int code) {
sneakyThrow(new Throwable(msg + ": " + code, ex));
}
#SuppressWarnings("unchecked")
private <T extends RuntimeException> void sneakyThrow(Throwable t) throws T {
throw (T) t;
}
}

May I throw an AssertionError in an EJB method?

Following the style used in Joshua Bloch's Effective Java and in agreement with the answers to this question, I've used AssertionErrors in the past in the Java SE environment for code paths that should never possibly be executed.
Looking at Java EE, the EJB 3.1 specification says
If the bean method encounters a system exception or error, it should simply propagate the error from the bean method to the container (i.e., the bean method does not have to catch the exception).
and a little further down, it says that the concerned EJB instance has to be discarded in the case of a non-ApplicationException. As far as I know, if another instance of that EJB is required in a subsequent request, the container takes one from the pool or creates a new one if necessary, so there should be no problems associated with that (except of course if it was a #Singleton EJB).
Is it appropriate/good style to use an AssertionError in a session bean method for indicating programming errors? Or is there a more fitting Throwable subtype for that?
I don't really see anything wrong in throwing an AssertionError. The container should be able to perform a rollback, just as it would for any unckecked exceptions.
Having said that, I never throw AssertionErrors myself. A couple of common examples where I would throw a subclass of RuntimeException, which is probably more appropriate than AssertionError, are:
Say we have an enum:
public enum TestEnum {
TEST1, TEST2;
}
I want to catch the default case, in this I throw an IllegalArgumentException:
public class TestClass {
public void doSomethingWithTestEnum(TestEnum testEnum) {
switch (testEnum) {
case TEST1:
// do something here
break;
case TEST2:
// do something here
break;
default:
throw new IllegalArgumentException("Unknown enum type: " + testEnum);
}
}
}
Another example would be parameter validation:
public class TestClass {
private String testString;
public TestClass(String testString) {
this.testString = Objects.requireNonNull(testString);
}
}
Here, a NullPointerException is thrown if testString is null.
There are probably cases where an assertion would be more suitable, but honestly I never encounter them.

How to bind to CheckedProvider in guice?

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...

Throwing an Exception Not Defined in the Interface

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.

Categories