Search code examples
javafunctional-programmingvavrcyclops-react

How to map a "Try with resources" exception type?


In a Cyclops React "Try with Resources" block, I would like to map an IOException to a custom exception type. I have tried this also with Javaslang and seems less fexible since it treats all exceptions the same.

Code example:

private static Try<String, ConnectionError> readString() {
    // Socket is a thread-local static field
    final Try<String, IOException> string = Try.catchExceptions(IOException.class)
            .init(() -> new BufferedReader(new InputStreamReader(socket.get().getInputStream())))
            .tryWithResources(BufferedReader::readLine);

    return string.isSuccess() ? Try.success(string.get()) :
            Try.failure(new ConnectionError("Could not read from server", string.failureGet()));
}

Could this be done in more elegant way? Or does not make any sense and it would be better to return Try<String, IOException>?

Disclaimer: I am a newbie using the Cyclops React library and functional programming in general, so I may have severe conceptual miscomprehensions.


Solution

  • Starting with Javaslang 2.1.0 it will be possible to do the following:

    Try<String> of = Try.withResources(() -> new BufferedReader(new InputStreamReader(socket.get().getInputStream())))
                        .of(BufferedReader::readLine)
                        .mapFailure(
                            Case(instanceOf(IOException.class), ConnectionError::new)
                        );
    

    I.e. we added the Try.withResources functionality and are now able to map a failure.

    The mapFailure method takes a variable amount of match cases. When the exception is not matched (and therefore not mapped), the original exception remains.

    I think it makes no sense to include an exception type as part of the Try signature, e.g. Try<String, IOException>, because a computation may throw one of several exceptions.

    Specifying a set of possible exception types also does not help because the type information gets lost when the compiler computes the upper bound of the generic.

    Disclaimer: I'm the creator of Javaslang