Hi Sameera,

I came across a the topic of exception handling in functional interfaces
when going through the book 'Java 8 for the Really Impatient - Cay S.
Horstmann' which was recommended by my mentor Azeez.
The book however says that what is suggested is a solution but not a
complete fix.

The suggested solution is to use functional interfaces whose methods allow
checked exceptions. For example, the *T get( ) *method of functional
interface *Supplier<T>* do not allow checked exceptions. But, the
functional interface *Callable<T>* has a method that is declared as *T
call( ) throws exception*, which allows checked exceptions. Therefore, the
fix would be to use *Callable<T>* instead of *Supplier<T>*.  I tried this
fix for an example. [1]

In the example given, stream.map( ) method maps objects to another value as
specified by a Function<T,R> object. Since a functional interface that
allows checked exceptions corresponding to* Function<T,R>* is not
available, I created a functional interface called *CheckedFunction<T,R>* which
has a single abstract method that throws a *ClassNotFoundException*.  I
have replaced the *Function<T,R>* interface using *CheckedFunction<T,R>* by
writing the *unchecked* method.

import java.util.function.Function;
import java.util.stream.Stream;

public class Example {

    public static void main(String[] args) {
        Stream.of("java.lang.String", "java.lang.Integer")
                .map(unchecked(Class::forName))
                .forEach(System.out::println);
    }

    public static <T, R> Function<T, R> unchecked(CheckedFunction<?
super T, ? extends R> function) {
        return arg -> {
            try {
                return function.apply(arg);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        };
    }
}

interface CheckedFunction<T, R> {
    R apply(T t) throws ClassNotFoundException;
}


​
According to the book, we can implement a version of the *unchecked *method
to deal with lambdas that throws checked exceptions, given that we can find
or provide a functional interface whose abstract method throws arbitrary
exceptions.

[1] https://lochanaranaweera.wordpress.com/2015/11/27/417/


Thanks and regards,

On Wed, Mar 2, 2016 at 11:41 AM, Sameera Jayasoma <same...@wso2.com> wrote:

> You cannot throw checked exceptions from inside Lambda expression/Streams
> in Java 8. This is a well-known issue and there are tons of discussions
> about this. Oracle has not provided a solution yet. Some people say that
> Oracle messed it up. Anyway developers around the globe have come up with
> several workarounds. With C5 effort, we are starting to use Java 8 heavily.
> Therefore we need to agree on a workaround soon.
>
> You probably need to have some experience with Java 8 Lambdas and Streams
> in order to understand this issue. Lets me explain some of the Java 8
> concepts briefly. I am using few sample code snippets extracted from
> various sources.
>
> *Introduction to Java8*
>
> *Streams* - Represents a sequence of elements. Streams supports
> sequential and parallel aggregate operations. In the following example, If
> an element starts with "c", then the element is converted to uppercase. All
> such converted elements are sorted and output to the System.out. JVM
> invokes these operations in an optimized manner, not necessarily in the
> order we've specified.
>
> List<String> list = Arrays.asList("a1", "a2", "b1", "c2", "c1");
>
> list
>     .stream()
>     .filter(s -> s.startsWith("c"))
>     .map(String::toUpperCase)
>     .sorted()
>     .forEach(System.out::println);
>
> // C1
> // C2
>
>
> *Lambda Expression* - Represents a function which can be created and
> passed around without belonging to any class. This function can be executed
> on demand as well. Take a look at the following example.
>
> list
>     .stream()
>     .filter(s -> s.startsWith("c"))
>
> Expression inside the filter method is called a lambda expression which
> takes a String object as an argument and returns a boolean. Lambda
> expressions are equivalent to interfaces with one abstract method. This is
> how lambda expressions are modeled in Java8. These interfaces are called
> Functional Interfaces in Java 8. Following is a sample functional
> interface. Above lambda expression is mapped to the following functional
> interface that comes with Java by default. A point to note is that, None of
> these standard functional interfaces available in Java 8 allow to forward
> checked exceptions to the caller.
>
> @FunctionalInterfacepublic interface Predicate<T> {
>     boolean test(T t);}
>
> Now that you have a brief understanding of some of the Java 8 features,
> let's look at the problem related to checked exceptions.
>
>
> *Checked Exceptions and Stream, Lambdas, Functional Interfaces*
>
> The test method of the Predicate interface has not declared any exceptions
> in the method signature. What if a checked exception is thrown inside an
> implementation of the test method, how can we forward this exception to the
> caller of the test method. There is no straight-forward way to solve this
> issue. One workaround would be to throw a RuntimeException which wraps the
> checked exception. It is not a very elegant solution though.
>
> Let me take an example to illustrate this issue more clearly.
>
> public List<Class> getClasses() throws* ClassNotFoundException* {
>     Stream.of("java.lang.String", "java.lang.Integer")
>             .map(className -> Class.forName(className))
>             .foreach(clazz -> System.out.println(clazz.getName());}
>
> Above code snippet doesn't compile. Why? Class.forName() method throws a
> checked exception called ClassNotException, but its not possible to throw
> this exception from the lambda expression. You could deal with this problem
> in the following manner. But it is not a proper solution.
>
> public List<Class> getClasses() throws* ClassNotFoundException* {
>     Stream.of("java.lang.String", "java.lang.Integer")
>             .map(className -> {
>                    try {
>                         return Class.forName(className);
>                    } catch(ClassNotFoundException e) {
>                         e.printStackTrace();                        throw new 
> RuntimeException(e);
>                   }            })            .foreach(clazz -> 
> System.out.println(clazz.getName());}
>
> We need to find a better workaround to this issue. I found one such
> workaround by googling. I will test it and update this thread ASAP. In the
> meantime, if you can think of a proper workaround, please update this
> thread. If required we can have a meeting to discuss this further.
>
> Thanks,
> Sameera.
>
> [1]
> http://stackoverflow.com/questions/27644361/how-can-i-throw-checked-exceptions-from-inside-java-8-streams
> [2] https://dzone.com/articles/java-8-functional-interfaces-0
> [3]
> http://programmers.stackexchange.com/questions/225931/workaround-for-java-checked-exceptions
>
> --
> Sameera Jayasoma,
> Software Architect,
>
> WSO2, Inc. (http://wso2.com)
> email: same...@wso2.com
> blog: http://blog.sameera.org
> twitter: https://twitter.com/sameerajayasoma
> flickr: http://www.flickr.com/photos/sameera-jayasoma/collections
> Mobile: 0094776364456
>
> Lean . Enterprise . Middleware
>
>
>
> _______________________________________________
> Architecture mailing list
> Architecture@wso2.org
> https://mail.wso2.org/cgi-bin/mailman/listinfo/architecture
>
>


-- 
Lochana Ranaweera
Intern Software Engineer
WSO2 Inc: http://wso2.com
Blog: https://lochanaranaweera.wordpress.com/
Mobile: +94716487055 <http://tel%2B716487055>
_______________________________________________
Architecture mailing list
Architecture@wso2.org
https://mail.wso2.org/cgi-bin/mailman/listinfo/architecture

Reply via email to