I have a problem with the handling of exceptions, without the use of try and catch, in lambdas.
I found example code for which I need to make my own Consumer interface, but it doesn't work and I don't know how to fix it.
import java.util.function.Consumer;
#FunctionalInterface
public interface ThrowingConsumer<T, E extends Exception> {
void accept(T t) throws E;
static <T> Consumer<T> throwingConsumerWrapper(
ThrowingConsumer<T, Exception> throwingConsumer) {
return i -> {
try {
throwingConsumer.accept(i);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
};
}
}
Here is the lambda in which I need to handle IOException. This exception must be thrown from main. I do not wish to use try and catch in main.
public static void main(String[] args) throws IOException {
Function<String, List<String>> flines = fileName -> {
Scanner scanner;
ArrayList<String> wiersze = new ArrayList<>();
File f = new File(fileName);
scanner = new Scanner(f); // here :(
while (scanner.hasNext()) {
wiersze.add(scanner.nextLine());
}
scanner.close();
return wiersze;
};
}
I am new to Java, so please could you explain to me how to fix this problem in the easiest way.
So is your problem that you have a piece of code that throws a checked exception, and you want that to become the implementation of a Function object? You've found somewhere how to do it for Consumer, you just need the code adapter for Function?
Assuming that the rewrite should look something like:
import java.util.function.Function;
#FunctionalInterface
public interface ThrowingFunction<T, R, EXC extends Exception> {
R apply(T t) throws EXC;
static <T> Function<T> throwingFunctionWrapper(
ThrowingFunction<T, R, Exception> throwingFunction
) {
return t -> {
try {
return throwingFunction.apply(t);
} catch (Exception exc) {
throw new RuntimeException(exc);
}
};
}
}
To be a little more general, throwingFunctionWrapper could be:
static <T> Function<T> throwingFunctionWrapper(
ThrowingFunction<T, R, ? extends Exception> throwingFunction
) {
In order to deal with the exception you should subclass RuntimeException and then only catch that class, so as to not unwrap any other runtime exceptions.
Unwrap (with the original code) as:
try {
...
} catch (RuntimeException exc) { // subclass me !!
throw (IOException)exc.getCause();
}
Related
How could I wrote a ThrowingSupplier with an unchecked method that could replace this part of code? I have really no idea how to start with it should it be an interface or rather a class.
try {
// get connection with the database
connection = dataSource.getConnection();
} catch (Exception e) {
throw new UndeclaredThrowableException(e);
}
What I would like to get is something like
Connection connection = ThrowingSupplier.unchecked(dataSource::getConnection).get();
Any ideas how should it looks like? I am not sure if it should be an interface or a class I tried to wrote that, but then I could not create a static method unchecked and I would not to create new instance of that.
If I understand correctly, this is what you want:
public class ThrowingSupplier {
public static <T> Supplier<T> unchecked(Callable<T> callable) {
return () -> {
try {
return callable.call();
}
catch (Exception e) {
throw new UndeclaredThrowableException(e);
}
};
}
// example usage:
public static void main(String[] args) {
DataSource dataSource = null;
Connection connection = ThrowingSupplier.unchecked(dataSource::getConnection).get();
}
}
I want to do this:
Observable.just(bitmap)
.map(new Func1<Bitmap, File>() {
#Override
public File call(Bitmap photoBitmap) {
//File creation throws IOException,
//I just want it to hit the onError() inside subscribe()
File photoFile = new File(App.getAppContext().getCacheDir(), "userprofilepic_temp.jpg");
if(photoFile.isFile()) {//delete the file first if it exists otherwise the new file won't be created
photoFile.delete();
}
photoFile.createNewFile(); //saves the file in the cache dir
FileOutputStream fos = new FileOutputStream(photoFile);
photoBitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);//jpeg format
fos.close();
return photoFile;
}
})
.subscribe(//continue implementation...);
Basically in the call() method, it can throw exceptions. How can I make the Observer handle it in onError(). Or is this not the right way to think about this?
rx will always catch error, even if this is RuntimeException.
So you can throw Some kind of Runtime exception in catch block. This is how actually it should work.
Observable.just(bitmap)
.map(b -> {
try {
// do some work which throws IOException
throw new IOException("something went wrong");
} catch (IOException e) {
throw new RXIOException(e);
// Or you can use
throw Exceptions.propagate(e);
// This helper method will wrap your exception with runtime one
}
}).subscribe(o -> {
// do something here
}, exception -> exception.printStackTrace());
public static class RXIOException extends RuntimeException {
public RXIOException(IOException throwable) {
super(throwable);
}
}
With 1.0.15, there is the fromCallable factory method which let's you run a Callable instance for each subscriber where you can throw checked exceptions as well:
Observable.fromCallable(() -> {
File photoFile = new File(App.getAppContext().getCacheDir(),
"userprofilepic_temp.jpg");
if (photoFile.isFile()) {
//delete the file if it exists otherwise the new file won't be created
photoFile.delete();
}
photoFile.createNewFile(); //saves the file in the cache dir
FileOutputStream fos = new FileOutputStream(photoFile);
photoBitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);//jpeg format
fos.close();
return photoFile;
})
.subscribe(...)
Edit:
source.flatMap(v -> {
try {
//...
return Observable.just(result);
} catch (Exception e) {
return Observable.error(e);
}
})
.subscribe(...);
Just created helper class to extract this boilerplate to another place:
public class RxRethrow {
public static <T, R> Func1<T, R> rethrow(Func1R<T, R> catchedFunc) {
return t -> {
try {
return catchedFunc.call(t);
} catch (Exception e) {
throw Exceptions.propagate(e);
}
};
}
public interface Func1R<T, R> extends Function {
R call(T t) throws Exception;
}
}
You can call it like this:
.map(RxRethrow.rethrow(products -> mapper.writer(schema).writeValueAsString(products)))
I don't know how the situation was when this question was first asked and answered, but RxJava currently contains a helper-method for this exact purpose:
Exceptions.propagate(Throwable t)
RxJava Javadoc
Convenience method to throw a RuntimeException and Error directly or wrap any other exception type into a RuntimeException.
I have a lambda expression, which can throw a IOException:
Function<String, List<String>> readFile = path-> {
try {
return Files.readAllLines(
Paths.get((String) path), Charset.forName("UTF-8"));
} catch (IOException e) {
return null;
}
};
I would like to write the same lambda expression without using the try {} catch {} block, so that the exception would be rethrown to the enclosing function:
public static void main(String[] args) throws IOException {
Function<String, List<String>> readFile = path-> {
try {
return Files.readAllLines(
Paths.get((String) path), Charset.forName("UTF-8"));
} catch (IOException e) {
return null;
}
};
}
The only problem is that I cannot define my own interfaces/classes and I can only use interfaces provided by Java APIs.
Would that be possible?
If you want to rethrow the excepion, you can use RuntimeException.
Add this to your catch body.
throw new RuntimeException(e);
Since Function.apply does not throw checked exceptions, you cannot do it ...
... in a legal way. However, you can consider "sneaky throw" if you can take the risk
interface FunctionX<T,R, X extends Exception> extends Function<T,R>
{
R applyX(T t) throws X;
#Override
default R apply(T t)
{
try
{
return applyX(t);
}
catch (Exception x)
{
throw Util.sneakyThrow(x);
}
}
public static <T,R,X extends Exception>
FunctionX<T,R,X> of(FunctionX<T,R,X> f){ return f; }
}
// Util.java
public static RuntimeException sneakyThrow(Throwable t)
{
throw Util.<RuntimeException>sneakyThrow0(t);
}
#SuppressWarnings("unchecked")
private static <T extends Throwable> T sneakyThrow0(Throwable t) throws T
{
throw (T)t;
}
Usage example
Function<String, List<String>> readFile = FunctionX.of( path-> {
return Files.readAllLines(
Paths.get(path), Charset.forName("UTF-8"));
} );
readFile.apply("/no-file");
What is the best pattern for using Google Guava with methods that should throw exceptions?
Let's say I have:
public Sting someMethod(Integer i) throws SomeException;
And I want to do:
List<String> s=Lists.transform(is,new Function<String, Integer>() {
public String apply(Integer i) {
return someMethod(i);
}
});
I couldn't do the above because of the exception. Is there any nice pattern for handling it?
Propagate the checked exception as a RuntimeException:
try {
return someMethod(i);
} catch (SomeException e) {
throw new RuntimeException(e);
}
EDIT: Since the transformed list is lazily evaluated, the exception won't be thrown until you access the list elements. You can force the evaluation by copying the transformed list into a new list, like:
s = new ArrayList<>(s);
You could wrap that in a try-catch block that catches RuntimeException and handles it however you want; your original SomeException instance can be obtained by calling getCause() on the RuntimeException. Or you could just let the RuntimeException bubble up.
You can use
public interface FunctionWithException<T, R, E extends Exception> {
public R apply(T t) throws E;
}
It depends on how you want to handle the exception.
Stop the list transformation when an exception occurs: See #dnault's answer.
Continue the list transformation and remove the element which caused exception (and log some error message).
In this case, we will return null when an exception occurs, this null value will be removed from final list:
List<String> s = Lists.newArrayList(
Iterables.filter(
Iterables.transform(l, new Function<Integer, String>() {
#Override
public String apply(Integer i) {
try {
return someMethod(i);
} catch (SomeException e) {
e.printStackTrace();
return null;
}
}
}), Predicates.notNull()))`
EDIT
If someMethod can return null value then you should a wrapper like this one:
class Wrapper {
public Exception exception = null;
public String result = null;
}
The list transformation will then be:
List<Wrapper> wrappers = Lists.newArrayList(
Iterables.filter(
Iterables.transform(l, new Function<Integer, Wrapper>() {
#Override
public Wrapper apply(Integer i) {
Wrapper wrapper = new Wrapper();
try {
wrapper.result = someMethod(i);
} catch (SomeException e) {
wrapper.exception = e;
}
return wrapper;
}
}), new Predicate<Wrapper>() {
#Override
public boolean apply(Wrapper wrapper) {
return wrapper.exception == null;
}
}));
The java code:
public static <T extends Throwable> void checkNotNull(Object value, String name, Class<T> exceptionClass) throws T, SecurityException, IllegalArgumentException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
if (value==null)
throw ExceptionHelper.constructException(exceptionClass, name + " should not be null");
}
static <T extends Throwable> T constructException(java.lang.Class<T> exceptionClass, String message) throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
Constructor<T> constructor = exceptionClass.getConstructor(String.class);
T result = constructor.newInstance(message);
return result;
}
The junit code:
#Test
public void testCheckNotNull() {
try {
ValidationUtility.checkNotNull(null, "valuename", exceptionClass);
} catch (T e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Then the compiler says: Cannot use the type parameter T in a catch block
So how to solve this issue?
Since T is not known at compile time, you can't use it in a catch block like that. It is simply not something that is supported by the compiler, hence the error.
If your intent is to verify that the correct exception is thrown, I would suggest modifying your Test code like this:
#Test
public void testCheckNotNull() {
try {
ValidationUtility.checkNotNull(null, "valuename", exceptionClass);
} catch (Throwable e) {
assertEquals(exceptionClass, e.getClass());
}
}
By
Constructor<T> constructor = exceptionClass.getConstructor(String.class);
T result = constructor.newInstance(message);
You are creating result object of class passed as argument. Here by using 'T', only it means that you are constructing the result with the class which extends Throwable.
In the test method, even if do like this declare it:
#Test
public <T extends Throwable> void testCheckNotNull() {
try {
ValidationUtility.checkNotNull(null, "valuename", exceptionClass);
} catch (T e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Still T is a type, not a class e.g. Exception which can be caught. As you have found in the error, you will not be able to catch a Type.
Since you know, Type T is representing classes extending Throwable, use may want to use Throwable in the catch block.
} catch (Throwable e) {
As specified in earlier answer you cannot catch T. This is because of erasure. I would suggest using the JUnit4 expected if you are expecting an exception.
#Test(expected = Throwable.class)
public void testCheckNotNull() throws Throwable {
ValidationUtility.checkNotNull(null, "valuename", exceptionClass);
}
There is a bug with your test code too. If no exception is thrown then the test will still pass. You need to have a fail in there too
#Test
public void testCheckNotNull() {
try {
ValidationUtility.checkNotNull(null, "valuename", exceptionClass);
fail("expected to throw")
} catch (Throwable e) {}
}