1

I have a function

public ShoppingCart fetchCart(Long storeId) throw NotFoundException {
    ///
}

Then I was trying to assign this function to another one by using

Function<Long, ShoppingCart> func = e -> {
    fetchCart(e)
}

But it always telling me that the exception is not handled. But when I tried to add try/catch around the function assignment, then my "Function<Long, ShoppingCart> func" is not getting the exception.

Is there a way to do this and also capture the original function's exception? Thanks!

Some more context. I'm doing this since I want the func to be given to another function as parameter so this func can another one can be run in parallel... like compare the values of these functions even their exceptions. Thus the function is essential to be captured not in fetchCart..

user13902742
  • 505
  • 1
  • 4
  • 6
  • In my opinion best solution is to handle exception inside fetchCart method – Martin Pechacek Jan 28 '21 at 20:37
  • Hi pirho, but I was not using a @FunctionalInterface as mentioned in the post... I want this func to be assigned to fetchCart and then pass it to another function so this one and another function can be run in parallel. kinda like a parallel framework.. – user13902742 Jan 28 '21 at 20:46
  • Using the anotation `@FunctionalInterface` is not necessary it is just good practice. The interface Function has the annotation too, so you are using it. – matt Jan 28 '21 at 21:06
  • In the true nature of java 8 and exploding the number of interfaces, you can make a `FindableFunction` which does something like `R apply(T input) throws NotFoundException`. Then you would specify you're looking for a `Function` named `FindableFunction`, aka a function that can throw your specified exception. A real world example of this for me would be `SQLFunction`, which has `throws SQLException`. – Rogue Jan 28 '21 at 21:16

2 Answers2

0

You could wrap the exception into a runtime exception and then handle this runtime exception by the caller.

Function<Long, ShoppingCart> func = e -> {
    try {
        return fetchCart(e);
    } catch (NotFoundException notFoundException) {
        throw new RuntimeException(notFoundException);
    }
}

complete code in one file would be then:

import java.util.function.Function;

public class ShoppinCartCaller {

    public ShoppingCart fetchCart(Long storeId) throws NotFoundException {
      return null;
    };

    public static class NotFoundException extends Exception {

    }

    public static class ShoppingCart {
    }

    Function<Long, ShoppingCart> func = e -> {
        try {
            return fetchCart(e);
        } catch (NotFoundException notFoundException) {
            throw new RuntimeException(notFoundException);
        }
    };
}
juwil
  • 422
  • 3
  • 9
  • Ni juwili, no I cannot do this. Since it has compile error at throw new RuntimeException(notFoundException); asking me to add try/catch – user13902742 Jan 28 '21 at 20:50
  • where would my posted code have a compiler error? I above append a working example below my prior code - for ease of reading in one source file.. – juwil Jan 28 '21 at 21:01
0

I think your problem is NotFoundException is a checked exception. Checked Exceptions (not RuntimeException subclasses) can not be thrown in a lambda. A workaround is to catch it and rethrown inside a RuntimeException as its cause.

Eg:

Function<Long, ShoppingCart> func = e -> {
        try {
            return fetchCart(e);
        } catch (NotFoundException ex) {
            RuntimeException re = new RuntimeException();
             re.initCause(ex);
             throw re;
        }
        return null;
    };

Then, when you will catch the runtimeException, you will have to handle its cause.

try {
    /// call func here
} catch(Exception e) {
    ((NotFoundException)e.getCause()).printStackTrace();
}
g.momo
  • 536
  • 2
  • 7