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

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;
}
}

Related

subclass throw UnsupportedOperationException versus ignoring input parameter

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.

What is the best runtime exception to use when mandatory input is missing

I have service, a simple class that need to take input and run some business logic. Before executing this service, the user must set all the data. In general, it look like this:
public class TestService extends InnerServiceBase {
/**
* Mandatory input
*/
private Object inputObj;
#Override
protected ErrorCode executeImpl() {
//Some business logic on inputObj
return null;
}
public void setInputObj(Object inputObj) {
this.inputObj = inputObj;
}
}
What is the best runtime exception to throw in case the inputObj is null ?
IllegalStateException seems like the best fit. The object is not in the correct state to have executeImpl() called on it. Whatever exception you use, make sure the error message is helpful.
Whether you should be using an unchecked exception at all is a whole other question...
Depends on the scenario.
If this is part of an API that another developer is using, throwing NullPointerException is reasonable since you don't want that input to be null. Adding a descriptive exception message would be helpful.
If you're not interested in throwing an NPE, or this is part of code that's not going into an API, then you could throw an IllegalArgumentException, as null could be considered an illegal argument.
If setInputObj is called with a null argument, and that's not valid, then throw NullPointerException. There's some debate over the "correct" exception here (IllegalArgumentException or NullPointerException for a null parameter?), but Guava, Apache Commons Lang and even the JDK itself (Objects.requireNonNull) have settled on NPE.
If executeImpl is called before inputObj has been set, throw IllegalStateException.

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

Should I throw IllegalArgmentException when 'user of given id not exist'?

Say we have a method changeUserName(Long id,String newName) which invokes the repository's findUser(Long id) to find the right user entity and then change its name. Is it appropriate to thow an IllegalArgmentException when findUser returns null ? Or should I instead throw a custom UserNotExistException (extends AppException extends RuntimeException) ?
UPDATE:
RuntimeException:
#nachokk #JunedAhsan Actually I deliberately make all the exceptions unchecked , because I think this way makes client code clean , easy for debuging and more safe. As to those "unhandled" ones, I'll catch them all on the top of layers thus avoiding showing them on the UI.
This is due to the fact that many clients catch checked exceptions and then just ignore it, and in some cases they don't know how to handle it. This is a hidden trouble.
Clarification:
Sorry for my bad English. What I meant is if the changeUserName should throw an IllegalArgumentException, not the findUser method. And another question: how to differentiate illegal argument from business rule violation?
You should use UserNotExistException. The name is very declarative of what is happening. In my opinion you should to avoid returning null but if you do you have to document it.
UPDATE
I was thinking and as #JunedAhsan suggest, UserNotExistException could be better a CheckedException (extends from Exception and not RuntimeException).
From this link: Unchecked Exceptions : Controversy
If a client can reasonably be expected to recover from an exception,
make it a checked exception. If a client cannot do anything to recover
from the exception, make it an unchecked exception.
/**
* #return User found or throw UserNotExistException if is not found
*/
public User findUser(Long id) throws UserNotExistException{
//some code
User user = giveMeUserForSomePlace();
if(user == null){
throw new UserNotExistException();
}
return user;
}
It depends on how you handle exceptions.
IllegalArgumentException is ok if you only display error report by using e.getMessage() and you don't care repetitive string appending code.
Here is some advantage I find by using custom exceptions:
1. Reduce reptetive code:
Let's say changeUserName is surely not the only case you'll load User, so this code snippet below will happen everytime you invoke repository.findUser(Long id)
if (user == null) {
throw new IllegalArgumentException("No such user found with given id["+ userId +"]");
}
On the other hand, an ad-hoc exception is much more handy:
if (user == null) {
throw new UserNotExistException(userId);
}
public class UserNotExistException extends RuntimeException {
public UserNotExistException(Long id) {
super("No such user found with given id["+ id +"]");
}
}
2. You need more support from your exceptions:
Maybe you need to return status code or something like that. An custom exception hierachy may do some help:
see this answer for detail.
I would too suggest to use UserNotExistException but with a difference that instead of it being unchecked exception (by virtue of extending RuntimeException), make it checked exception (extending Exception if AppException is not doing this already).
This will make sure that caller of changeUserName handles UserNotExistException exception and make the code a bit robust.

How to return an error message (String) from a constructor?

Requirements:
Section is created by selecting one teacher, one subject and one
schedule.
System verifies that all business rules are followed.
System detects that a business rule is not being followed.
System informs user of conflict.
System doesn't create new section.
3.System creates new section.
My problem is, if I define a constructor for section, Section(Teacher t, Subject s, Schedule c), I don't know how to return the error message for the conflict.
Should I just let my constructor throw an exception? If yes, how to return a string from a caught exception? How to create that exception?
Or is there any better, yet simple, implementation?
Reporting constructor failure boils down to two options:
Throw an exception as you suggest. This is a reasonable approach if failure is not expected to happen often and is truly "exceptional".
If failure is a normal part of the business logic, I'd recommend using the Factory pattern and returning a wrapper object that contains the newly created object plus a status variable that can indicate the detailed causes of the failure when it occurs.
You can throw the exception for sure.
throw new Exception("Some required files are missing");
Or create a new Exception to be used in your app (it will work the same way)
If you want to read the message inside of a try / catch statement just do this:
try
{
// ...
}
catch(Exception ex)
{
System.out.println(ex.getMessage()); //this will get "Some required files are missing"
}
For more information checke these links out:
http://en.wikibooks.org/wiki/Java_Programming/Throwing_and_Catching_Exceptions
How to throw a general exception in Java?
http://docs.oracle.com/javase/6/docs/api/java/lang/Throwable.html#getMessage()
It isn't possible to return a value from a constructor. Your only way to do this is to throw an exception of some sort. You can either use an existing exception type (if there are any applicable) or create your own by extending Exception. For example:
public class MyException extends Exception {
public MyException(){
super();
}
public MyException(String message){
super(message);
}
}
Your constructor would simply throw a new instance of the exception and set an appropriate message. The code creating the class instance would catch the exception and handle it. You can obtain the message at that point by calling getMessage().

Categories