Play Framework - Interfaces for methods that use Promise.failure(exception) - java

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.

Related

Using exception classes to model errors

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

The role of runtime exceptions in defining a methods “contract” and expressing the intentions of an operation and a classes ADT

Could it be said that RuntimeException's may play a role in defining an operation, as part of the notion of a classes ADT and a particular operations "contract".
Since one chooses to include chosen runtime exceptions in the 'throws' list in a methods header (as well as a methods javadoc) - it is not forced by the compiler and is discretionary depending upon the exception - could this not be considered an effort to emphasize something about the intention of a methods "contract" and how it should be understood to work? Is this the case?
We recognize that some RuntimeExceptions's are simply thrown as "errors" for program logic that needs correcting during development and testing, whereas others could be considered to perform a similar role to that of checked exceptions. Here by embodying instances where a handleable and recoverable situation may occur - a client user should be able to take some reasonable action to allow the sw system to recover and respond appropriately. One designs an ADT and an operation to emphasize how it should be used. I wondered (considering the above) if we should consider as part of this:
"The conveying to the client developer of the need to handle certain Runtime Exception's that can sensibly be handled and anticipated"?
Do we consider the declaration of RuntimeException's in an operations header and documentation to be signalling such an intention and expectation by the code/ API developer to the client user?
Emphasizing the RuntimeExceptions it may throw by declaring them in a throws section (that one should thus handle) and or, declaring them in a javadoc (that one should instead potentially just be aware of) could perhaps be considered as part of this “contract” - that one should understand and uphold in defining and working with an interface (an operation). Therefore, by choosing to emphasize certain RuntimeExceptions (which are a choice), could this therefore be a part of the concept of "design by contract" that one shapes and expresses – it is about intention (what a method should provide as a service, but (pertinant here) - how the method is intended to be used by a client and his/ her expected responsibilities)?
Also, if/ or what, is the relationship between the throwing and documenting of Runtime Exceptions and the software design principle of design by contract is?
Another way of looking at my question i suppose is - One can catch a runtime exception if desired. I think the vast majority of cases where a runtime exception might occur and is thrown relate to situations that never or should never occur in correct client code. Most of these situations relate to incorrect logic or misuse of a method (and handling code would be excessively numerous and not sensible to include in these situations). However, in some less frequent cases, it is possible for some runtime exceptions to be situations that one could (and should) handle. This is why I think (I interpret I coud be wrong), the compiler doesn't require one to handle runtime exceptions - the compiler cannot tell the difference. It cannot distinguish. Checked exceptions are almost always sensibly handleable, but most runtime exceptions are likely not. The nature of a runtime error governs this. – Another angle on my question I suppose relates to the notion that the latter can sometimes be the case and are we supposed to consider this as part of the contract we emphasize as described above and the software design principle of "design by contract"?
Since neither the throws clause is required by the Compiler for subclasses of RuntimeException if you throw one in a method, nor is it required to catch them if you call such a method, it is just for documentation.

Clear and simple rules for deciding between checked and unchecked exceptions

Since there is a lot of ambiguity about this, can we come up with some clear, simple and easy to use rules?
Here is a first try, these three rules should be sufficient for all cases.
First rule is based on the common principle that implementation details of the method should not be exposed to the caller:
Rule 1:
Checked exception should not expose implementation details to the caller:
You can test it this way: If you completely change the implementation but still expect the method to fulfill its contract (like in refactoring) would it still make sense to throw the exception?
If yes then it should be a Checked exception because it is not implementation detail but part of use case the method fullfills.
If no then the exception should be unchecked because it is an implementation detail which should not be exposed to the caller.
If based on Rule 1 the exception should be checked then apply the Rule 2:
Rule 2: Since checked exception is part of the method contract, violation of the method's contract can't be a checked exception.
For example this method executes sql query from its param:
executeSqlQuery(String sqlQuery)
If caller provides string that is not an sql query then he violated input conditions of the method and the resulting exception must be unchecked.
If based on Rule 2 the exception still seems like checked, apply rule three which checks whether the method is following another best practice: single responsibility principle
Rule 3: Method should do just one thing.
For example method
List.get(int index)
is correctly doing just one thing: returning desired element from the list. And not trying to also fulfill another common use cases: check whether the element is present.
On the other hand method
findById(Long id) throws RecordNotFoundException
is incorrectly trying to mix these two functions and by that forces all callers to always consider the use case when record is not found even though they know that the record exists.
Is some rule missing or can we simplify and clarify the rules further?
BACKGROUND:
There are many different views on this topic. There is quite a lot of proponents of "radical" solutions like never to use a checked exception (some java books or designers of C#) or that almost everything should be a checked exception (IOException in java.io package or SQLException in JDBC).
And at least same number of views suggest to use both types but are offering subjective and ambiguous rules for deciding between them which without a lengthy explanation that is often missing instead of helping just bring more confusion (eg: If it is reasonable for the caller to recover from the exception than it should be checked. Is trying the call again a reasonable recovery? For some clients it may be. Words reasonable and recover are too ambiguous.)
Um, that question is answered in the official Java Tutorials, in fact:
Here's the bottom line guideline: 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.
That looks like a pretty clear, simple rule to me.
EDIT: your background edit explains your confusion and frustration quite well. If you want to, I can come up with a even simpler rule:
Always be usable. Try to be practical where possible. Strive to be consistent.
The point is that exception handling is something that the user of the method that might throw must do. Sadly, Java forces the person who writes that method to make the choice for the user of that method. Thus, I'm leaning slightly towards the "never do checked" side, because your methods will always be usable. For some cases, for example network I/O, it might be really practical to force the user to build in some error handling, but that's not really often the case. If you're asking yourself hm, my last 400 methods all threw RuntimeErrors, should this now throw a checked exception?, attaining consistence might make using your library more practical.
Sadly, this rule is easier, but not clearer, because at least practical and consistent are very subjective notions. So here you are, stuck with something that is really a question of style.
The fundamental problem with the way Java handles checked exceptions is that while it would be useful to distinguish exceptions that get thrown for expected reasons (e.g. getRecordById throwing a RecordNotFoundException when given an ID that doesn't exist) from those which get thrown for unexpected reasons (e.g. a method which calls getRecordId for an ID which is supposed to exist, but doesn't), the type of an exception has little to do with whether it's coming from a method for reasons that method knows about, or because it was unexpectedly thrown in a nested method call.
If Java allowed exception instances to be marked as "expected" or "unexpected", with distinct statements for catching expected and unexpected ones as well as a means of indicating that any methods within a block aren't expected to throw certain exceptions (and if any such exceptions that are thrown are marked as "expected", they should be flagged "unexpected" before propagating out) then having certain methods declared as throwing "expected" exceptions would be useful. Given the present architecture, however, it's better to simply declare most exceptions as being unchecked.

Java: Throwing exceptions

Is it a good idea to pass an object to a constructor when throwing an exception?
Let's imagine that there is next code somewhere in service package.
throw new MyException(object);
MyException class:
Object object;
public MyException(Object object) {
super();
this.object = object;
}
public Object getObject() {
return object;
}
And later, let's say, in GUI we have to handle the exception thrown in service. We just catch an exception and want to access object passed in the constructor. This works. But is it a correct from the point of style?
Is the use of getObject() a correct approach?
I would say it depends on what you are doing with getObject. If you are just using it to report the error or manage the recovery from the exception then there's nothing wrong with this. I would pass something more specific than an object. For example, I might give the exception information about the cause of the error and capture any useful information that might help solve the error.
If, on the other hand, you are using this object to continue some normal branch of control flow, then that wouldn't be considered a normal use of exceptions! To repeat the obvious, exceptions are for exceptional situations and nothing more. If you're doing something else with them it's generally bad idea.
If you are using an exception to capture results that you are processing later then that's a bad design smell. Look at refactoring your code to write those objects out to a store for processing later, or some such. Don't abuse exceptions.
In general, yes, it's good to add data to exception objects which might be useful to the code handling the exception.
However, a getObject() method that returns an Object is way too generic - the name of the method and preferably also the type of the object should be specific to the exception - create multiple exception classes if necessary, then you can distinguish them in catch blocks.
Finally, this kind of thing could be abused for regular control flow. I do not agree with the standard dogma that this is inherently "evil" - exceptions are a control flow mechanism. But they're one that's bad for maintainability because it connects pieces of code implicitly. So it should only be used if you really need a way to pass control flow several levels up the call stack and have thought hard about alternatives.
As always, it will depend on your system strtucture and on what you want to achieve, but IMO this is an acceptable way to go.
Indeed, this is the way the default exception API handles the error messages and causes, passing them as constructor parameters (see Exception constructors API Doc) to be handled later.
The class that catches the exception depends on the (static) class of the object that is encapsulated in the exception. It's usually a good idea to minimize dependencies. That's why I would not encapsulate classes, that are internal to a component, into exceptions. I would encapsulate public classes of a component in an exception only if the exception and the encapsulated class belong to the same component.

How should I return a value from function?

Three ways I see here:
1) make function return that value explicitly
2) add additional argument to the function's argument list and pass string holder as that parameter. After the function completes its execution, that string holder will contain the result of the function.
3) throw an exception from that function that will contain the result.
I for myself see first choice more preferable because it's simple, intuitive and straight.
On the other hand, when execution of the function goes in a wrong way there may be additional choices like throw an exception or use a variable passed through parameter to save errors if any happen.
Intuitively, I see that ideal choice is to have explicit return value and throws declaration. So return value is used for normal execution and caught exception will signal about abnormal situation. But I myself don't like exceptions too much if only it is not the completely unpredictable error, so I'd use explicit return value and additional parameter to hold some extra-situation logs or errors.
Please advise books or articles on the subject (it shouldn't necessary talk about Java, any other languages with similar mechanisms are also suitable).
You absolutely want option #1. Exceptions are not unpredictable; if you use them correctly, they are in fact entirely predictable. You can throw different exception types based on the error (FileNotFoundException, IllegalArgumentException, SomeConditionSpecificToMyAppException, etc), and those exceptions can contain any error or diagnostic information you need to convey.
Here's a good section in the Java SE tutorial on exceptions: http://docs.oracle.com/javase/tutorial/essential/exceptions/
Java methods have return values for a reason: to return their results. In the vast majority of cases #1 should be your only choice. Even if you want to return a wrapper object e.g. because you need to return multiple values, you should probably just return the thing...
Exceptions are just that: they are thrown in exceptional (i.e. abnormal) circumstances. Since traditionally throwing an exception also implies a performance impact, exceptions should not be thrown during normal operation.
Why are you trying to confuse yourself?
EDIT:
On the other hand, exceptions are quite suitable for rare/abnormal conditions:
They have built-in support for the generation of debugging information. Getting a stack trace is half the battle in dealing with most bugs.
All decent debuggers allow for thrown exceptions to be used as a break point, which can be invaluable.
Exceptions allow for error conditions to be passed up the method call chain relatively transparently, allowing for the error handling code to be placed with as much granularity as desired.
Exceptions are the standard way to deal with error conditions in Java. This should be enough for most programmers. Please respect the people that will have to work with your code and don't break such basic conventions by reinventing the wheel...
I would use choice 1 almost every time. There is nothing stopping you throwing a Exception as required.
Please read Code Complete by Steve McConnell. It's all there.

Categories