Aside from NoSuchFieldException being a checked exception, where NoSuchElementException is not, what are the differences between the two exceptions? When should one be used as opposed to the other?
Specifically, I am working on an OOP representation to encapsulate Valve Server Query A2S_INFO Packets, where some values can be present or not depending on the value for the Extra Data Flag (EDF) (more specifically, the presence of these values can be tested using bit-wise AND with given constants.) The getter methods should provide the value if it is present, and throw an exception if not. This is where the initial question comes from, as I don't know what would be more beneficial to use here.
The code below shows one of the getter methods for a field that can be present or not depending on the value of the EDF:
public long getSteamID(){
if(containsSteamID){
return steamID;
}else{
//Should NoSuchElementException be used here or NoSuchFieldException?
throw new NoSuchElementException("There is no steamID in this packet.");
}
}
NoSuchFieldException is for reflection based access, it (quoting the docs) "signals that the [Java] class doesn't have a field of a specified name." The documentation also shows (at least for checked exceptions) from which JDK methods it is thrown. Since you are not using Java reflection, NoSuchFieldException seems inappropriate.
NoSuchElementException may be suitable, but it is (at least by the JDK) mostly used for generic collection and container classes.
Maybe IllegalStateException would be more appropriate in your situation:
Signals that a method has been invoked at an illegal or inappropriate time. In other words, the [...] Java application is not in an appropriate state for the requested operation.
However, if you are designing a wrapper library, maybe defining your own exception class (possibly as part of an exception hierarchy) would be the best solution. This gives you all the freedom to decided whether the exception should be checked or not and give it a meaningful name. This way users of your library can directly see that the exception comes from your library and possibly be able to better handle the exception than a generic NoSuchElementException which could have been thrown by completely unrelated code as well.
Related
Let's start with the Javadocs:
IllegalStateException
Signals that a method has been invoked at an illegal or inappropriate
time. In other words, the Java environment or Java application is not
in an appropriate state for the requested operation.
IllegalArgumentException
Thrown to indicate that a method has been passed an illegal or
inappropriate argument.
The problem with the above is that they are very black and white. Consider a use case where a method is parsing a file provided by the caller. The file exists, is readable, and is in the correct format. However, some content in the file is non-compliant with the business rules. What would be an appropriate exception to throw in this case - IllegalStateException or IllegalArgumentException?
Looking at various libraries that provide assertions, like Guava Preconditions or Spring Assert, it appears that there is no consensus. There are some good discussions here and here, but none provide a conclusive answer to the common use case I stated above.
Putting in other words:
The IllegalArgumentException is thrown in cases where the type is accepted but not the value, like expecting positive numbers and you give negative numbers.
The IllegalStateException is thrown when a method is called when it shouldn't, like calling a method from a dead thread.
I don't see how they could mix. In your question about the file with problems, I think that throwing either a ParseException or an IOException would be more appropriate.
IllegalStateException is for coding errors, not input errors. It's for when the invariants of a class have been violated, or a method is called when an object is in the wrong state. Examples are using a closed resource, or closing a resource twice.
IllegalArgumentException is when an argument has an invalid value per the method API. Passing -1 when only positive numbers are allowed.
In this case neither exception is appropriate. I would create a sub-class of IOException since there's an error in an input file.
The other answers highlight when to use IllegalArgumentException or IllegalStateException. But in my view (note: opinion based) these exceptions should not be used in your use case.
To summarize: Some file contains data in a valid format, is successfully loaded into the application but some values are not compliant to your business rules (Note: No IO operations failed, the format is valid => neither IOException nor ParseException should be used, they indicate failed IO operations or invalid formats).
Why you should not use IllegalArgumentException?
This exception is thrown to indicate that a method has been passed an illegal or inappropriate argument. You could argue that you have a method validating the file and the value of a field or the combinations of values of several fields in this file are illegal or non-compliant to your business rules. Yepp, point to you. But if you throw an IllegalArgumentException in this situation you can not separate IllegalArgumentExceptions caused by other libraries (or the standard library or from your own code somewhere else) and the IllegalArgumentExceptions from your validator which indicate a business rule violation easily (sure, you could subclass IAE and catch it in a calling method).
Why do you want to separate these exceptions? Use case: Business rule violations should be presented to the user so he can change his non-compliant inputs. Other IAE's or general any uncatched runtime exception indicates that the request failed on the server for example. In these cases you have to send different responses to clients.
You can argue in a similar way why IllegalStateExceptions should not be used to indicate business rule violations. So, what should be used in your use case?
This depends highly on the scale of your application. Some custom subclass of RuntimeException may do the Job for small applications. For larger applications validation libraries like "javax.validation" are worth a try.
I also think that the two methods have a very close semantic.
According to the IllegalArgumentException javadoc, passing an invalid argument may be handled by throwing IllegalArgumentException :
Thrown to indicate that a method has been passed an illegal or
inappropriate argument.
But invoking a method with a bad argument may also be handled by throwing IllegalStateException as its javadoc states that :
Signals that a method has been invoked at an illegal or inappropriate
time.
Indeed, invoking a method with an inappropriate or illegal argument may also mean that the method was invoked at an illegal or inappropriate time.
To make simple, I think that IllegalArgumentException and IllegalStateException may be used in a interchangeable way by some developers as the issue is caused by the passed argument(s). What I explained above.
While IllegalStateException use cases that are not related to a passed argument have not to be interchanged with IllegalArgumentException.
The nuance being slight, most of libraries mix sometimes their usage.
I am afraid to not be able to give you a more solid explanation.
Semantic is semantic and as two things may be interpreted in a closer way, it is often not clearly used.
Consider a use case where...
And if those were the only two options I had, in your use-case, I'd lean towards IllegalStateException
Why? Because the argument's are valid, they point to a file, which can be read. It's not the argument that is invalid, it's the fact that parsing the file would invalid the state.
This of course assumes that IllegalStateException and IllegalArgumentException are the only exceptions you are considering.
This is course just MHO. I think the important aspect is, you can define the reasons for using one exception over another in a consistent way which makes your API understandable.
I also agree with Saclyr (+1 to their answer), there are more appropriate exceptions you could use to define why the method call failed (personally, I'd consider java.text.ParserException)
Most of the programming languages do not have checked exceptions (like C# and Kotlin).
So, I'm trying to find a better approach for a case that I have in my project without using checked exceptions.
The project uses Java and we control the possible validation errors from a Remote EJB. Something like this:
lookupSomeRemoteEjb().createCustomer(/** lots of informations */);
This method throws many exceptions of validation, like:
DocumentoAlreadyExistsException();
InvalidNameException();
InvalidBirthDateException();
And etc.
This exceptions can happen in different classes in different levels. Like this example:
CustomerRemoteEjb.class // tell to the another system what error happened
CustomerService.class //can throw some errors about customer
PersonService.class // can throw some errors about person
DocumentService.class // can throw some errors about document
AddressService.class // can throw some errors about address
An API calls this remote EJB and catch every single error, translating this for a nice message to the API user (that uses this remote EJB).
Works well, but the code is a messy with a lot of ugly try/catch for each call.
I suppose that the alternative is use unchecked exceptions with an ID error or using something like a Result object with the same kind of ID for the validation error.
But this solutions don't fit very well in a more complex code (a monolyth system, by the way), because many times these validations are made from a service called by another service. It will be strange this deep services return exception (or result objects) with an ID to another services before they reach the API.
I read some old discussion about the alternative for checked exceptions, but there are no conclusion about the best alternative. I still agree with a comment there:
I'm reading the above discussion and I'm still left not knowing if exceptions are any good.
So, in a similar situation, how can I resolve this problem with languages that do not support checked exceptions?
Using different checked exceptions has in deed a fundamental problem: it introduces version compatibility issues. In case the two sides can have different code levels, you have to worry about the ejb side using "newer" exceptions...
Your question gives one potential solution (by using some return object). But there is another option: instead of having zillions of different exceptions - you can go for a single exception. And that exception carries some kind of error id.
Meaning: the user error message isn't derived from the exception type, but from some numerical id for example. Of course, this approach has other drawbacks - but still it solves (some of) the problems you run into when using the "one exception class per problem" approach.
For checked exceptions, you could use only one generic SystemException. And this it would solve the 'catching multiple exceptions' problem.
However SystemException need to have information about your exceptions like errorCodes and/or messages for the integrations (like Remote EJB) use them.
For Legacy Code, I would suggest:
Turn all the LegacySpecificException extending
SystemException (or)
Turn all the LegacySpecificException into SystemException
Another problem: If you need to "try-catch" another exception rather than SystemException(EJBException for example), you'll need to treat that and rethrow a SystemException.
} catch (EJBException e) {
throw new SystemException(e.getMessage(), e);
}
*ref: https://northconcepts.com/blog/2013/01/18/6-tips-to-improve-your-exception-handling/
For the types of exceptions you list:
DocumentoAlreadyExistsException();
InvalidNameException();
InvalidBirthDateException();
You could write a validation method that validates the input and returns a validation data value object. This validation method and data value object will evolve as the application evolves and the complexity of the validation is encapsulated in this method and will probably exist in its own class (and may call on other classes to do other specific tasks).
You could then do one of a number of options.
You could create a single Exception class ValidationException that has the validation data value object as an instance variable. At the beginning of your original method call the validation method, create and throw an instance of the validation exception class with the validation data value object as an instance variable.
You could call the validation method prior to the call to the original method and not call the original method if validation fails.
Both.
Many of the built in Java exceptions have no way to accept a "cause". Is there any way to assign a cause to these exceptions?
I want to be able to chain exceptions, like with this InterruptedException example:
try{
//threaded code
}catch (InterruptedException e){
throw new InterruptedException("context-specific information", e);
}
If a constructor like this does not exist, what is the reasoning?
Edit: I've considered throwing either a different exception or runtime exception that accepts a cause parameter. The reason I haven't gone with either of these options is because I'm working within a framework that expects an InterruptedException, and not some other exception type.
The logical reason for an exception class missing a way to attach a cause, is that they can't have another exception as a cause.
Taking the exceptions given as examples, we've got InterruptedException and UnsupportedAudioFileException. Neither of those will have an exception as a cause, since InterruptedException cannot occur because of other exceptions, but only if a thread is interrupted.
UnsupportedAudioFileException on the other hand could take a cause, but it would be useless. There's no "deeper" reason for an audio file to not be supported.
Therefore it's no suprise that NullPointerException doesn't take a cause either. It's not like there are many reasons for that to happen...
If you're using an exception that doesn't take a wrapped exception in the constructor, you're probably using an exception that wasn't designed for that sort of use. While the ready made "general exceptions" like IllegalArgumentException do take (and even expect) causes to be included, if you can't find an existing one that fits your use case, create your own exception.
If you're working with a framework that expects an InterruptedException, there are 2 possibilities. Either it was chosen because of the name ("Hey, stopping this job should throw InterruptedException") or it was chosen because of sane design choices. You should first make sure you're not using the framework wrong, since InterruptedException is not a general use case exception and implies interrupted threads.
Is there any way to assign a cause to these exceptions?
Yes; you can use the initCause(Throwable) method, which allows a cause to be set. It can only be called once for a given exception instance; it's specifically intended for this sort of case.
If a constructor like this does not exist, what is the reasoning?
Oddly enough, even though the great majority of JDK exceptions do support taking causes, the Javadoc for java.lang.Throwable seems to suggest that that's not the expected default. The Javadoc describes a few reasons that you might want to wrap an exception (neither of which applies in your case: they both have to do with wrapping an exception of one type in an exception of a different type), and it says that the cause-accepting constructors should only be created for "throwable classes that wish to allow causes to be associated with them" or even just for "subclasses that might likely have a cause associated with them" (emphasis mine).
I wonder if it's just that the JDK is behind the times; apparently causes were not originally intended to be used quite as generally as we now expect?
I want to know whether it would be right to use exception classes as regular classes to handle application errors (just regular controlled errors, not exceptional ones), without throwing them with the proper language clause (eg. instantiating them and returning them from a method). I've been discussing this topic recently with some colleges and I think that exceptions should only be used as exceptions, but I'd like to listen to more opinions.
What you mean by "controlled error" is actually known by the name checked exception.
"Exceptional exceptions" are known as unchecked exceptions.
The difference is explained here: Checked vs Unchecked exception
So, you see: Java comes with a built-in mechanism to distinguish between
exceptions caused by programming mistakes (e.g. NullPointerException when passing unexpected null as an argument) -- unchecked exceptions
versus anticipated exceptions that should be handled by the caller (e.g. IOException when some kind of I/O went wrong) -- checked exceptions
Returning instances of Exception (or any subclass) would be considered a misuse in virtually all circumstances.
You could ask your colleague how he/she would implement an exceptional outcome of a method with this signature:
public String createStringOrFailWithException();
Returning an Exception? Certainly not, because this requires a different return type.
Throwing the exception instead allows you to keep the return type, and to benefit from vast exception handling capabilities, including finally blocks and try-with-resources statements, to give only two examples that you don't want (should not) implement by yourself.
I suggest keeping Exceptions "exceptional". I.e. don't build them into your app logic. Use more meaningful things like a ActionXResponse class etc that could indicate failure, and even have an Exception as a property which the controller could check for "controlled exceptions". It's much more meaningful when you have your own class as a response.
Another guideline I'd suggest, along with keeping Exceptions "exceptional" is to avoid checked Exceptions (compile-time).
Background
Java interfaces specify the contract between the caller and callee sides of development. For example:
public interface SomeContainer<T> {
public boolean add(T value) throws SomeException;
}
The above method must return either a boolean or throw the given exception, and nothing else.
Problem Description
How can I do the same for a Play Promise-based method? A promise does not "throw" an exception; rather, a promises executes Promise.failure(ExceptionHere). Hence, my interface doesn't "throw" anything:
public interface SomeContainer<T> {
public Promise<boolean> add(T value);
}
However, the above definition does not prevent the implementating class from executing Promise.failure()--not a very good interface definition.
One possibility is to return a "Result" object which can contain the boolean or one of several allowed exceptions. However, this seems hackish, and still does not prevent the implementing code from calling Promise.failure() anyway.
Question
How does one write an effective Play Promise-based interface, where all return values and all acceptable exceptions are specified and nothing else is allowed?
What you're describing is a fundamental limitation of exceptions - their specification only works when they are thrown directly from a method. The problem is not specific to promises, it manifests itself all over the place, anytime you package execution of something up into a generic interface, which is especially pertinent when using lambdas. Consider doing a List.forEach, that doesn't throw an exception, but typically you will pass a lambda to it (which will implement java.util.function.Function), what if that lambda throws an exception? The answer is, it can't, unless it's an unchecked exception, and then there's no way to know statically that that exception will be thrown through to the caller of forEach.
The only real answer is don't use exceptions. If you talk to a functional programming purist, they will say never, ever use exceptions, instead of exceptions you should use a disjoint type. Play's Java API actually provides such a type, it's play.libs.F.Either. Convention is that the left should be the error, and the right the value. That said, Play's either type is quite limited, and doesn't compose very well with itself or other things. The either type provided by the Functional Java library is much more complete, and composes well. If you value being as strict as possible about type safety, in particular with exceptions, then this is probably the library for you, even without using promises, encoding errors into return types offers better type safety than exceptions, and makes it very straight forward to compose and reuse error handling. And if that sounds like a good option to you, then you should also consider using a language with stronger typing than Java, eg Scala.
If you're like me though and are little more pragmatic about things, then you'll use a hybrid approach. In some cases, it's really important for the caller to explicitly handle errors, in which case, they should be encoded in the types, an example of this is form validation, you don't just want to throw an error, you want to handle it by rendering a page with multiple meaningful error messages in it - this is a perfect example of where strongly typed error handling really shines, you can return a list of errors, one for each field that had a problem in a form, but you can't throw a list of exceptions. In other cases, errors really are exceptional things that don't usually have a specific handling strategy, instead they should be left to a general catch all high up in the stack to handle generically. For example, if the database is down, that's not something that you can usually recover from. In these cases, you lose nothing by throwing unchecked exceptions and letting the generic error handling do its thing.