In Scala application, am trying to read lines from a file using java nio try-with-resource construct.
Scala version 2.11.8
Java version 1.8
try(Stream<String> stream = Files.lines(Paths.get("somefile.txt"))){
stream.forEach(System.out::println); // will do business process here
}catch (IOException e) {
e.printStackTrace(); // will handle failure case here
}
But the compiler throws error like
◾not found: value stream
◾A try without a catch or finally is equivalent to putting its body in a block; no exceptions are handled.
Not sure what is the problem. Am new to using Java NIO, so any help is much appreciated.
If your are on Scala 2.13 then you should use the Using object:
import scala.util.Using
val a: Try[Int] = Using(new FileInputStream("/tmp/someFile")) { fileInputStream =>
// Do what you need in fith you fileInputStream here.
}
It takes two functions. The first one is a function that can create or provide the closable resource, and the second function is the one that takes the closable resource as a parameter, and can use it for something. Using will then in simple terms do the following for you:
Call the first function to create the closable resource.
Call the second function, and provide the resource as a parameter.
Hold on to the returned value of the second function.
Call close on the resource.
Return the value (or exception) it got from the second function wrapped in a Try.
Using can be used on many other things than Classes that implements AutoCloseable, you just have to provide an implicit value, telling Using how to close your specific resource.
In older versions of scala, there is no directly support for javas try-with-resources construct, but your can pretty easy build your own support, by applying the loan pattern. The following is a simple but not optimal example, that is easy to understand. A more correct solution is given later in this answer:
import java.lang.AutoCloseable
def autoClose[A <: AutoCloseable,B](
closeable: A)(fun: (A) ⇒ B): B = {
try {
fun(closeable)
} finally {
closeable.close()
}
}
This defines a reusable method, that works pretty much like a try-with-resource construct in java. It works by taken two parameter. First is takes the a subclass of Autoclosable instance, and second it takes a function that takes the same Autoclosable type as a paremeter. The return type of the function parameter, is used as return type of the method. The method then executes the function inside a try, and close the autocloseble in its finally block.
You can use it like this (here used to get the result of findAny() on the stream.
val result: Optional[String] = autoClose(Files.lines(Paths.get("somefile.txt"))) { stream ⇒
stream.findAny()
}
In case your want to do catch exceptions, you have 2 choices.
Add a try/catch block around the stream.findAny() call.
Or add a catch block to the try block in the autoClose method. Note that this should only be done, if the logic inside the catch block is usable from all places where autoClose is called.
Note that as Vitalii Vitrenko point out, this method will swallow the exception from the close method, if both the function supplied by the client, and the close method on the AutoCloseable throws an exception. Javas try-with-resources handles this, and we can make autoClose do so to, by making it a bit more complex:
def autoClose[A <: AutoCloseable,B](
closeable: A)(fun: (A) ⇒ B): B = {
var t: Throwable = null
try {
fun(closeable)
} catch {
case funT: Throwable ⇒
t = funT
throw t
} finally {
if (t != null) {
try {
closeable.close()
} catch {
case closeT: Throwable ⇒
t.addSuppressed(closeT)
throw t
}
} else {
closeable.close()
}
}
}
This works by storing the potentially exception the client function throws, and adding the potential exception of the close method to it as a supressed exception. This is pretty close to how oracle explains that try-with-resource is actually doing it: http://www.oracle.com/technetwork/articles/java/trywithresources-401775.html
However this is Scala, and a lot of people will prefer to program in a more functional way. In a more functional way, the method should return a Try, instead of throwing an exception. This avoids a side effect of throwing an exception, and makes it clear to the client that the response may be a failure that should be handled (as pointed out in the answer by Stas). In a functional implementation, we would also like to avoid having a var, so a naive attempt could be:
// Warning this implementation is not 100% safe, see below
def autoCloseTry[A <: AutoCloseable,B](
closeable: A)(fun: (A) ⇒ B): Try[B] = {
Try(fun(closeable)).transform(
result ⇒ {
closeable.close()
Success(result)
},
funT ⇒ {
Try(closeable.close()).transform(
_ ⇒ Failure(funT),
closeT ⇒ {
funT.addSuppressed(closeT)
Failure(funT)
}
)
}
)
}
This could them be called like this:
val myTry = autoCloseTry(closeable) { resource ⇒
//doSomethingWithTheResource
33
}
myTry match {
case Success(result) ⇒ doSomethingWithTheResult(result)
case Failure(t) ⇒ handleMyExceptions(t)
}
Or you could just call .get on myTry to make it return the result, or throw the exception.
However as Kolmar points out in a comment, this implementation is flawed, due to how the return statement works in scala. Consider the following:
class MyClass extends AutoCloseable {
override def close(): Unit = println("Closing!")
}
def foo: Try[Int] = {
autoCloseTry(new MyClass) { _ => return Success(0) }
}
println(foo)
We would expect this to print Closing!, but it will not. The problem here is the explicit return statement inside the function body. It makes the method skip the logic in the autoCloseTry method, and thereby just returns Success(0), without closing the resource.
To fix that problem, we can create a mix of the 2 solutions, one that has the functional API of returning a Try, but uses the classic implementation based on try/finally blocks:
def autoCloseTry[A <: AutoCloseable,B](
closeable: A)(fun: (A) ⇒ B): Try[B] = {
var t: Throwable = null
try {
Success(fun(closeable))
} catch {
case funT: Throwable ⇒
t = funT
Failure(t)
} finally {
if (t != null) {
try {
closeable.close()
} catch {
case closeT: Throwable ⇒
t.addSuppressed(closeT)
Failure(t)
}
} else {
closeable.close()
}
}
}
This should fix the problem, and can be used just like the first attempt. However it shows that this a bit error prone, and the faulty implementation has been in this answer as the recommended version for quite some time. So unless you trying to avoid having to many libraries, you should properly consider using this functionality from a library. I think that there is already one other answer pointing to one, but my guess is that there is multiply libraries, that solves this problem in different ways.
Alternatively, you can use Choppy's (Disclaimer: I am the author) TryClose monad do this in a for-comprehension in a composeable manner similar to Scala's Try.
val ds = new JdbcDataSource()
val output = for {
conn <- TryClose(ds.getConnection())
ps <- TryClose(conn.prepareStatement("select * from MyTable"))
rs <- TryClose.wrap(ps.executeQuery())
} yield wrap(extractResult(rs))
Here's how you would do it with your stream:
val output = for {
stream <- TryClose(Files.lines(Paths.get("somefile.txt")))
} yield wrap(stream.findAny())
More info here:
https://github.com/choppythelumberjack/tryclose
You have the already mentioned in one of the answers approach:
def autoClose[A <: AutoCloseable, B](resource: A)(code: A ⇒ B): B = {
try
code(resource)
finally
resource.close()
}
But I think the following is much more elegant:
def autoClose[A <: AutoCloseable, B](resource: A)(code: A ⇒ B): Try[B] = {
val tryResult = Try {code(resource)}
resource.close()
tryResult
}
With the last one IMHO it's easier to handle the control flow.
Related
I'm reformatting some legacy code that I don't fully understand, and in it there are several variable assignments that conditionally assign variables to the output of one of two formatting functions, using exception catching like so:
String myString;
try {
myString= foo(x);
} catch (Exception e) {
myString= bar(x);
}
This seems like an abuse of exception handling, and anyway it's a lot of repeated boilerplate code for a lot of variable assignments. Without digging into foo to identify the conditions that might cause exceptions, can I simplify this using a ternary operator expression? I.e. something like this:
String myString = foo(x) ? foo(x) : bar(x)
but catching the exception that might be thrown by foo(x). Is there a way to do this in this one-liner? Or if not, is there a better one-line expression that chooses between two assignments based on a possible exception? I am using Java 8.
One could use lazy evaluation as follows:
String myString = attempt(() -> foo(x), () -> bar(x));
public static <T> T attempt(Supplier<T> a, Supplier<T> b) {
try {
return a.get();
} catch (Exception e) {
return b.get();
}
}
It is not nice and just would be one stage in the entire refactoring.
One pattern for such constructs you saw would be a result message of a process that maybe throws an IOException.
An ugly pattern would be a NullPointerException or such, when data is optional. Then
a complexer redesign with Optional.ofNullable and .map to another Optional might be feasible.
In short I do not see a clean way.
Washcloth answer is already clear. Just wanna add a bit though about your statement:
it's a lot of repeated boilerplate code for a lot of variable assignments.
If you don't want to assign a variable repeatedly, you can create a new method to return String value as below:
String myString = assign(x);
String assign(String x) {
try {
return foo(x);
} catch (Exception e) {
return bar(x);
}
}
You only need to assign the variable once with the above method.
Considering this case
String myString;
try {
myString= foo(x);
} catch (Exception e) {
myString= bar(x);
}
What would happen if foo(x) throws an exception because it can't handle strings with UTF-16 characters, then we would use bar(x) instead.
In your ternary operator case String myString = foo(x) ? foo(x) : bar(x) if you check foo(x) first and it throws an error your entire program would error out which leads us back to putting a try statement around your ternary operator.
Without the original code its hard to say why the developers did it this way but above is an outlined case as to why they chose this design practice. Also good to note that not all legacy code is bad, in this case; the legacy code works, is maintainable, and easy to read for new developers. So as the comment says, best to leave it this way.
Edit
You said you wanted some sort of 1 liner that reduces boiler plate. You could do something like this
void hee(String mystring) {
try {
myString= foo(x);
} catch (Exception e) {
myString= bar(x);
}
}
Putting this function in a utility class followed by changing myString = foo(x) to hee(x) would suffice since your original object X is not a primitive java type. This solution is backwards compatible (since this is legacy code I'm unsure what jdk you are using) and requires minimal explanation.
I have an Try<Option<Foo>>. I want to flatMap Foo into a Bar, using it using an operation that can fail. It's not a failure if my Option<Foo> is an Option.none(), (and the Try was a success) and in this case there's nothing to do.
So I have code like this, which does work:
Try<Option<Bar>> myFlatMappingFunc(Option<Foo> fooOpt) {
return fooOpt.map(foo -> mappingFunc(foo).map(Option::of) /* ew */)
.getOrElse(Try.success(Option.none()); // double ew
}
Try<Bar> mappingFunc(Foo foo) throws IOException {
// do some mapping schtuff
// Note that I can never return null, and a failure here is a legitimate problem.
// FWIW it's Jackson's readValue(String, Class<?>)
}
I then call it like:
fooOptionTry.flatMap(this::myFlatMappingFunc);
This does work, but it looks really ugly.
Is there a better way to flip the Try and Option around?
Note 1: I actively do not want to call Option.get() and catch that within the Try as it's not semantically correct. I suppose I could recover the NoSuchElementException but that seems even worse, code-wise.
Note 2 (to explain the title): Naively, the obvious thing to do is:
Option<Try<Bar>> myFlatMappingFunc(Option<Foo> fooOpt) {
return fooOpt.map(foo -> mappingFunc(foo));
}
except this has the wrong signature and doesn't let me map with the previous operation that could have failed and also returned a successful lack of value.
When you are working with monads, each monad type combine only with monads of same type. This is usually a problem because the code will come very unreadable.
In the Scala world, there are some solutions, like the OptionT or EitherT transformers, but do this kind of abstractions in Java could be difficult.
The simple solution is to use only one monad type.
For this case, I can think in two alternatives:
transform fooOpt to Try<Foo> using .toTry()
transform both to Either using .toEither()
Functional programmers are usually more comfortable with Either because exceptions will have weird behaviors, instead Either usually not, and both works when you just want to know why and where something failed.
Your example using Either will look like this:
Either<String, Bar> myFlatMappingFunc(Option<Foo> fooOpt) {
Either<String, Foo> fooE = fooOpt.toEither("Foo not found.");
return fooE.flatMap(foo -> mappingFunc(foo));
}
// Look mom!, not "throws IOException" or any unexpected thing!
Either<String, Bar> mappingFunc(Foo foo) {
return Try.of(() -> /*do something dangerous with Foo and return Bar*/)
.toEither().mapLeft(Throwable::getLocalizedMessage);
}
I believe this is simply a sequence function (https://static.javadoc.io/io.vavr/vavr/0.9.2/io/vavr/control/Try.html#sequence-java.lang.Iterable-) that you are looking for:
Try.sequence(optionalTry)
You can combine Try.sequence and headOption functions and create a new transform function with a little better look, in my opinion, also you can use generic types to get a more reusable function :) :
private static <T> Try<Option<T>> transform(Option<Try<T>> optT) {
return Try.sequence(optT.toArray()).map(Traversable::headOption);
}
If I understand correctly, you want to :
keep the first failure if happens
swap the second when mapping to json for an empty option.
Isn t it simpler if you decompose your function in such a way:
public void keepOriginalFailureAndSwapSecondOneToEmpty() {
Try<Option<Foo>> tryOptFoo = null;
Try<Option<Bar>> tryOptBar = tryOptFoo
.flatMap(optFoo ->
tryOptionBar(optFoo)
);
}
private Try<Option<Bar>> tryOptionBar(Option<Foo> optFoo) {
return Try.of(() -> optFoo
.map(foo -> toBar(foo)))
.orElse(success(none())
);
}
Bar toBar(Foo foo) throws RuntimeException {
return null;
}
static class Bar {
}
static class Foo {
}
The solution of throughnothing and durron597 helped me there. This is my groovy test case:
def "checkSomeTry"() {
given:
def ex = new RuntimeException("failure")
Option<Try<String>> test1 = Option.none()
Option<Try<String>> test2 = Option.some(Try.success("success"))
Option<Try<String>> test3 = Option.some(Try.failure(ex))
when:
def actual1 = Try.sequence(test1).map({ t -> t.toOption() })
def actual2 = Try.sequence(test2).map({ t -> t.toOption() })
def actual3 = Try.sequence(test3).map({ t -> t.toOption() })
then:
actual1 == Try.success(Option.none())
actual2 == Try.success(Option.some("success"))
actual3 == Try.failure(ex)
}
So our project back-end is a Java 8 Springboot application, springboot allows you to do some stuff really easily. ex, request validation:
class ProjectRequestDto {
#NotNull(message = "{NotNull.DotProjectRequest.id}")
#NotEmpty(message = "{NotEmpty.DotProjectRequest.id}")
private String id;
}
When this constraint is not meet, spring (springboot?) actually throws a validation exception, as such, we catch it somewhere in the application and construct a 404 (Bad Request) response for our application.
Now, given this fact, we kinda followed the same philosophy throughout our application, that is, on a deeper layer of the application we might have something like:
class ProjectService throws NotFoundException {
DbProject getProject(String id) {
DbProject p = ... // some hibernate code
if(p == null) {
Throw new NotFoundException();
}
return p;
}
}
And again we catch this exception on a higher level, and construct another 404 for the client.
Now, this is causing a few problems:
The most important one: Our error tracing stops being useful, we cannot differentiate (easily) when the exception is important, because they happen ALL the time, so if the service suddenly starts throwing errors we would not notice until it is too late.
Big amount of useless logging, on login requests for example, user might mistyped his password, and we log this and as a minor point: our analytics cannot help us determine what we are actually doing wrong, we see a lot of 4xx's but that is what we expect.
Exceptions are costly, gathering the stack trace is a resource intensive task, minor point at this moment, as the service scales up with would become more of a problem.
I think the solution is quite clear, we need to make an architectural change to not make exceptions part of our normal data flow, however this is a big change and we are short on time, so we plan to migrate over time, yet the problem remains for the short term.
Now, to my actual question: when I asked one of our architects, he suggested the use of monads (as a temporal solution ofc), so we don't modify our architecture, but tackle the most contaminating endpoints (ex. wrong login) in the short term, however I'm struggling with the monad paradigm overall and even more in java, I really have no idea on how to apply it to our project, could you help me with this? some code snippets would be really good.
TL:DR: If you take a generic spring boot application that throws errors as a part of its data flow, how can you apply the monad pattern to avoid login unnecessary amount of data and temporarily fix this Error as part of data flow architecture.
The standard monadic approach to exception handling is essentially to wrap your result in a type that is either a successful result or an error. It's similar to the Optional type, though here you have an error value instead of an empty value.
In Java the simplest possible implementation is something like the following:
public interface Try<T> {
<U> Try<U> flatMap(Function<T, Try<U>> f);
class Success<T> implements Try<T> {
public final T value;
public Success(T value) {
this.value = value;
}
#Override
public <U> Try<U> flatMap(Function<T, Try<U>> f) {
return f.apply(value);
}
}
class Fail<T> implements Try<T> {
// Alternatively use Exception or Throwable instead of String.
public final String error;
public Fail(String error) {
this.error = error;
}
#Override
public <U> Try<U> flatMap(Function<T, Try<U>> f) {
return (Try<U>)this;
}
}
}
(with obvious implementations for equals, hashCode, toString)
Where you previously had operations that would either return a result of type T or throw an exception, they would return a result of Try<T> (which would either be a Success<T> or a Fail<T>), and would not throw, e.g.:
class Test {
public static void main(String[] args) {
Try<String> r = ratio(2.0, 3.0).flatMap(Test::asString);
}
static Try<Double> ratio(double a, double b) {
if (b == 0) {
return new Try.Fail<Double>("Divide by zero");
} else {
return new Try.Success<Double>(a / b);
}
}
static Try<String> asString(double d) {
if (Double.isNaN(d)) {
return new Try.Fail<String>("NaN");
} else {
return new Try.Success<String>(Double.toString(d));
}
}
}
I.e. instead of throwing an exception you return a Fail<T> value which wraps the error. You can then compose operations which might fail using the flatMap method. It should be clear that once an error occurs it will short-circuit any subsequent operations - in the above example if ratio returns a Fail then asString doesn't get called and the error propagates directly through to the final result r.
Taking your example, under this approach it would look like this:
class ProjectService throws NotFoundException {
Try<DbProject> getProject(String id) {
DbProject p = ... // some hibernate code
if(p == null) {
return new Try.Fail<DbProject>("Failed to create DbProject");
}
return new Try.Succeed<DbProject>(p);
}
}
The advantage over raw exceptions is it's a bit more composable and allows, for example, for you to map (e.g. Stream.map) a fail-able function over a collection of values and end up with a collection of Fails and Successes. If you were using exceptions then the first exception would fail the entire operation and you would lose all results.
One downside is that you have to use Try return types all the way down your call stack (somewhat like checked exceptions). Another is that since Java doesn't have built-in monad support (al la Haskell & Scala) then the flatMap'ing can get slightly verbose. For example something like:
try {
A a = f(x);
B b = g(a);
C c = h(b);
} catch (...
where f, g, h might throw, becomes instead:
Try<C> c = f(x).flatMap(a -> g(a))
.flatMap(b -> h(b));
You can generalise the above implementation by making the error type an generic parameter E (instead of String), so it then becomes Try<T, E>. whether this is useful depends on your requirements - I've never needed it.
I have a more fully-implemented version here, alternatively the Javaslang and FunctionalJava libraries offer their own variants.
Not attempting to compare the languages but just for knowledge,
Is there any way to have equivalent of java throws keyword/functionality in Python?
or the way we can recognize checked exception thrown by any method at static time?
or Passing(chaining) exception handling responsibility?
Java:
public void someMethod() throws SomeException
{
}
Python:
#someDecorator # any way to do?
def someMethod():
pass
If you can't have statically typed arguments, you can't have static throws declarations. For instance, there's no way for me to annotate this function:
def throw_me(x):
raise x
Or even this one:
def call_func(f):
f() # f could throw any exception
What you can do is make it an error to throw any type of exception other than those specified:
from functools import wraps
class InvalidRaiseException(Exception):
pass
def only_throws(E):
def decorator(f):
#wraps(f)
def wrapped(*args, **kwargs):
try:
return f(*args, **kwargs)
except E:
raise
except InvalidRaiseException:
raise
except Exception as e:
raise InvalidRaiseException("got %s, expected %s, from %s" % (
e.__class__.__name__, E.__name__, f.__name__)
)
return wrapped
return decorator
#only_throws(ValueError)
def func(x):
if x == 1:
raise ValueError
elif x == 2:
raise Exception
>>> func(0)
>>> func(1)
ValueError
>>> func(2)
InvalidRaiseException: got Exception, expected ValueError, from func
There is no standard equivalent of this in Python as far as I know, and it's not necessary either. The best you can do is indicate in the docstring what exceptions/errors are raised in what circumstances, and leave it to whoever is using your functions to work out the rest.
In Java, the throws clause is a sort of bookkeeping. For example,
try {
foo();
} catch (IOException ioe) {
}
doesn't compile unless foo is known to have the potential of throwing an IOException. The analog in Python:
try:
foo()
except IOError as ioe:
pass
compiles regardless. There is no concept of "checked vs unchecked".
As an addition:
Python introduced Type-Hints for documentation purpose in PEP 484:
def foo(bar: str) -> int:
pass
As answered in Python type hinting with exceptions and https://www.python.org/dev/peps/pep-0484/#exceptions there is currently no way to define the Exceptiones which are raised by a function.
I'm playing with the new lambda features in Java 8, and found that the practices offered by Java 8 are really useful. However, I'm wondering is there a good way to make a work-around for the following scenario. Suppose you have an object pool wrapper that requires some kind of a factory to fill the object pool, for example (using java.lang.functions.Factory):
public class JdbcConnectionPool extends ObjectPool<Connection> {
public ConnectionPool(int maxConnections, String url) {
super(new Factory<Connection>() {
#Override
public Connection make() {
try {
return DriverManager.getConnection(url);
} catch ( SQLException ex ) {
throw new RuntimeException(ex);
}
}
}, maxConnections);
}
}
After transforming the functional interface into lambda expression, the code above becomes like that:
public class JdbcConnectionPool extends ObjectPool<Connection> {
public ConnectionPool(int maxConnections, String url) {
super(() -> {
try {
return DriverManager.getConnection(url);
} catch ( SQLException ex ) {
throw new RuntimeException(ex);
}
}, maxConnections);
}
}
Not so bad indeed, but the checked exception java.sql.SQLException requires a try/catch block inside the lambda. At my company we use two interfaces for long time:
IOut<T> that is an equivalent to java.lang.functions.Factory;
and a special interface for the cases that usually require checked exceptions propagation: interface IUnsafeOut<T, E extends Throwable> { T out() throws E; }.
Both IOut<T> and IUnsafeOut<T> are supposed to be removed during migration to Java 8, however there is no exact match for IUnsafeOut<T, E>. If the lambda expressions could deal with checked exceptions like they were unchecked, it could be possible to use simply like the following in the constructor above:
super(() -> DriverManager.getConnection(url), maxConnections);
That looks much cleaner. I see that I can rewrite the ObjectPool super class to accept our IUnsafeOut<T>, but as far as I know, Java 8 is not finished yet, so could be there some changes like:
implementing something similar to IUnsafeOut<T, E>? (to be honest, I consider that dirty - the subject must choose what to accept: either Factory or "unsafe factory" that cannot have compatible method signatures)
simply ignoring checked exceptions in lambdas, so no need in IUnsafeOut<T, E> surrogates? (why not? e.g. another important change: OpenJDK, that I use, javac now does not require variables and parameters to be declared as final to be captured in an anonymous class [functional interface] or lambda expression)
So the question is generally is: is there a way to bypass checked exceptions in lambdas or is it planned in the future until Java 8 is finally released?
Update 1
Hm-m-m, as far as I understand what we currently have, it seems there is no way at the moment, despite the referenced article is dated from 2010: Brian Goetz explains exception transparency in Java. If nothing changed much in Java 8, this could be considered an answer. Also Brian says that interface ExceptionalCallable<V, E extends Exception> (what I mentioned as IUnsafeOut<T, E extends Throwable> out of our code legacy) is pretty much useless, and I agree with him.
Do I still miss something else?
Not sure I really answer your question, but couldn't you simply use something like that?
public final class SupplierUtils {
private SupplierUtils() {
}
public static <T> Supplier<T> wrap(Callable<T> callable) {
return () -> {
try {
return callable.call();
}
catch (RuntimeException e) {
throw e;
}
catch (Exception e) {
throw new RuntimeException(e);
}
};
}
}
public class JdbcConnectionPool extends ObjectPool<Connection> {
public JdbcConnectionPool(int maxConnections, String url) {
super(SupplierUtils.wrap(() -> DriverManager.getConnection(url)), maxConnections);
}
}
In the lambda mailing list this was throughly discussed. As you can see Brian Goetz suggested there that the alternative is to write your own combinator:
Or you could write your own trivial combinator:
static<T> Supplier<T> exceptionWrappingSupplier(Supplier<T> b) {
return e -> {
try { b.accept(e); }
catch (Exception e) { throw new RuntimeException(e); }
};
}
You can write it once, in less that the time it took to write your
original e-mail. And similarly once for each kind of SAM you use.
I'd rather we look at this as "glass 99% full" rather than the
alternative. Not all problems require new language features as
solutions. (Not to mention that new language features always causes
new problems.)
In those days the Consumer interface was called Block.
I think this corresponds with JB Nizet's answer.
Later Brian explains why this was designed this way (the reason of problem)
Yes, you'd have to provide your own exceptional SAMs. But then lambda
conversion would work fine with them.
The EG discussed additional language and library support for this
problem, and in the end felt that this was a bad cost/benefit
tradeoff.
Library-based solutions cause a 2x explosion in SAM types (exceptional
vs not), which interact badly with existing combinatorial explosions
for primitive specialization.
The available language-based solutions were losers from a
complexity/value tradeoff. Though there are some alternative
solutions we are going to continue to explore -- though clearly not
for 8 and probably not for 9 either.
In the meantime, you have the tools to do what you want. I get that
you prefer we provide that last mile for you (and, secondarily, your
request is really a thinly-veiled request for "why don't you just
give up on checked exceptions already"), but I think the current
state lets you get your job done.
September 2015:
You can use ET for this. ET is a small Java 8 library for exception conversion/translation.
With ET you can write:
super(() -> et.withReturningTranslation(() -> DriverManager.getConnection(url)), maxConnections);
Multi line version:
super(() -> {
return et.withReturningTranslation(() -> DriverManager.getConnection(url));
}, maxConnections);
All you need to do before, is creating a new ExceptionTranslator instance:
ExceptionTranslator et = ET.newConfiguration().done();
This instance is thread safe an can be shared by multiple components. You can configure more specific exception conversion rules (e.g. FooCheckedException -> BarRuntimeException) if you like. If no other rules are available, checked exceptions are automatically converted to RuntimeException.
(Disclaimer: I am the author of ET)
We developed an internal project in my company that helped us with this. We decided to went public two months ago.
This is what we came up with:
#FunctionalInterface
public interface ThrowingFunction<T,R,E extends Throwable> {
R apply(T arg) throws E;
/**
* #param <T> type
* #param <E> checked exception
* #return a function that accepts one argument and returns it as a value.
*/
static <T, E extends Exception> ThrowingFunction<T, T, E> identity() {
return t -> t;
}
/**
* #return a Function that returns the result of the given function as an Optional instance.
* In case of a failure, empty Optional is returned
*/
static <T, R, E extends Exception> Function<T, Optional<R>> lifted(ThrowingFunction<T, R, E> f) {
Objects.requireNonNull(f);
return f.lift();
}
static <T, R, E extends Exception> Function<T, R> unchecked(ThrowingFunction<T, R, E> f) {
Objects.requireNonNull(f);
return f.uncheck();
}
default <V> ThrowingFunction<V, R, E> compose(final ThrowingFunction<? super V, ? extends T, E> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> ThrowingFunction<T, V, E> andThen(final ThrowingFunction<? super R, ? extends V, E> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
/**
* #return a Function that returns the result as an Optional instance. In case of a failure, empty Optional is
* returned
*/
default Function<T, Optional<R>> lift() {
return t -> {
try {
return Optional.of(apply(t));
} catch (Throwable e) {
return Optional.empty();
}
};
}
/**
* #return a new Function instance which wraps thrown checked exception instance into a RuntimeException
*/
default Function<T, R> uncheck() {
return t -> {
try {
return apply(t);
} catch (final Throwable e) {
throw new WrappedException(e);
}
};
}
}
https://github.com/TouK/ThrowingFunction/
Have you considered using a RuntimeException (unchecked) wrapper class to smuggle the original exception out of the lambda expression, then casting the wrapped exception back to it's original checked exception?
class WrappedSqlException extends RuntimeException {
static final long serialVersionUID = 20130808044800000L;
public WrappedSqlException(SQLException cause) { super(cause); }
public SQLException getSqlException() { return (SQLException) getCause(); }
}
public ConnectionPool(int maxConnections, String url) throws SQLException {
try {
super(() -> {
try {
return DriverManager.getConnection(url);
} catch ( SQLException ex ) {
throw new WrappedSqlException(ex);
}
}, maxConnections);
} catch (WrappedSqlException wse) {
throw wse.getSqlException();
}
}
Creating your own unique class should prevent any likelihood of mistaking another unchecked exception for the one you wrapped inside your lambda, even if the exception is serialized somewhere in the pipeline before you catch and re-throw it.
Hmm... The only thing I see that's a problem here is that you are doing this inside a constructor with a call to super() which, by law, must be the first statement in your constructor. Does try count as a previous statement? I have this working (without the constructor) in my own code.
Wrapping the exception in the described way does not work. I tried it and I still get compiler errors, which is actually according to the spec: the lambda expression throws the exception which is incompatible with the target type of the method argument: Callable; call() does not throw it so I can not pass the lambda expression as a Callable.
So basically there is no solution: we are stuck with writing boilerplate. The only thing we can do is voice our opinion that this needs fixing. I think the spec should not just blindly discard a target type based on incompatible thrown exceptions: it should subsequently check whether the thrown incompatible exception is caught or declared as throws in the invoking scope.
And for lambda expressions that are not inlined I propose we can mark them as silently throwing checked exception (silent in the sense that the compiler should not check, but the runtime should still catch).
let's mark those with => as opposed to ->
I know this is not a discussion site, but since this IS the only solution to the question, let yourself be heard and let's change this spec!
Paguro provides functional interfaces that wrap checked exceptions. I started working on it a few months after you asked your question, so you were probably part of the inspiration for it!
You'll notice that there are only 4 functional interfaces in Paguro vs. the 43 interfaces included with Java 8. That's because Paguro prefers generics to primitives.
Paguro has single-pass transformations built into its immutable collections (copied from Clojure). These transforms are roughly equivalent to Clojure transducers or Java 8 streams, but they accept functional interfaces that wrap checked exceptions. See: the differences between Paguro and Java 8 streams.
You can throw from your lambdas, they just have to be declared "with your own way" (which makes them, unfortunately, not re-usable in standard JDK code, but hey, we does what we cans).
#FunctionalInterface
public interface SupplierIOException {
MyClass get() throws IOException;
}
Or the more generic-ized version:
public interface ThrowingSupplier<T, E extends Exception> {
T get() throws E;
}
ref here. There is also a mention of using "sneakyThrow" to not declare the checked exceptions, but then still throw them. It that hurts my head a bit, maybe an option.
jOOλ is a library that supports wrapping all sorts of functional interfaces throwing checked exceptions into equivalent JDK functional interfaces. For example:
// Wraps the checked exception in an unchecked one:
Supplier<Class<?>> supplier = Unchecked.supplier(() -> Class.forName("com.example.X"));
// Re-throws the checked exception without compile time checking:
Supplier<Class<?>> supplier = Sneaky.supplier(() -> Class.forName("com.example.X"));
I've made some more examples in this blog post here.
Disclaimer: I made jOOλ