Java lambda not working with full definition - java

I am trying to wrap methods which throws checked exceptions.. I am following steps told in this url: https://www.rainerhahnekamp.com/en/ignoring-exceptions-in-java/
Interestingly when I write the code like this:
IntStream.range(1, locales.length)
.mapToObj(i -> locales[i].toString())
.forEach(wrap(this::testLocale));
it is working fine but when I write like this:
IntStream.range(1, locales.length)
.mapToObj(i -> locales[i].toString())
.forEach(s -> wrap(testLocale(s)));
Intellij is complaining "Unhandled Exception: java.lang.Exception"
here testLocale looks like this:
void testLocale(String s) throws Exception
The wrap function looks like this:
public static <T> Consumer<T> wrap(WrapConsumer<T> wrapper) {
return t -> {
try {
wrapper.accept(t);
} catch(Exception exception) {
throw new RuntimeException(exception);
}
};
}
and WrapConsumer is a function interface with Consumer signature:
#FunctionalInterface
public interface WrapConsumer<T> {
void accept(T t) throws Exception;
}
I am banging my head trying to understand why Intellij is complaining based on how I write the lambda

You are supposed to provide a wrapped consumer to forEach via:
.forEach(wrap(this::testLocale));
what you are doing via s -> wrap(testLocale(s)) is provide a new consumer that still can't handle the checked Exception.
Probably simpler to understand would be that forEach accepts a Consumer that has a method definition of:
void accept(T t); // does not define to throw the checked Exception
When you do forEach(s -> ...), it is this Consumer::accept that you are using.
On the other hand that forEach(wrap(this::testLocale)); will return a Consumer still, but by accepting as input a WrapConsumer<T> wrapper that does declare to throw that Exception via:
void accept(T t) throws Exception;

You're just missing the correct lambda syntax. Your current code is calling wrap with a void argument: wrap(testLocale(s)) - (testLocale(s) has a void return type)
The correct lambda expression that you need is:
.forEach(wrap(s -> testLocale(s)));
wrap returns a function, so you don't need delayed execution for it (i.e., no need for a function that calls wrap).

Just complementing what Eugene answered, you are expecting with the method wrap() a consumer as param, not a invocation method returning void.
You can prove this by removing the throws Exception from the testLocale method.
The IDE will them give you the error:
"reason: no instance(s) of type variable(s) T exist so that void conforms to WrapConsumer<T>"
The similar code for the one you wrote (right consumer):
IntStream.range(1, locales.length)
.mapToObj(i -> locales[i].toString())
.forEach(wrap(this::testLocale));
Would be:
IntStream.range(1, locales.length)
.mapToObj(i -> locales[i].toString())
.forEach(wrap(l-> testLocale(l)));

Related

How to chain vavr's Either nicely?

I have a function returning an Either<MyError, String> (function2) , which result depends on another function returning another Either<MyError, SomethingElse> (function1)
Both functions rely on a Try block that could fail, and I want to compose those two first function to create a "handle" which will be the main function of my class.
There are basically 3 scenarios possible :
function1 fails : I want handle to return the error given by function1
function1 succeeds and function2 fails : function2 must return its own error then returned by handle
both functions work : handle must return the String
Here is my current code :
private Either<MyError, Path> getPath(Arg arg) { // function 1
return Try.of(() -> //some code that can fail)
.toEither().mapLeft(e -> new MyError("Error message for function1", e));
}
private Either<MyError, String> getContent(Path path) { // function 2
return Try.of(() -> //some code that can fail)
.toEither().mapLeft(e -> new MyError("Error message for function2", e));
}
public Either<MyError, String> handle(Arg arg) {
return Either.right(arg)
.map(this::getPath)
.map(this::getContent);
}
Everything works except the Handle function, I think that my problem might be related to the use of Either::map function, that might not be the thing for my case.
Any thought about this ?
Also, sorry if the answer seems obvious, i am quite new to functionnal programming and vavr.
The method that could help to make this work would be flatMap.
So if you use flatMap instead of map, the handle method will become something like:
public Either<MyError, String> handle(Arg arg) {
return Either.<MyError, Arg>right(arg)
.flatMap(this::getPath)
.flatMap(this::getContent);
}
The scenarios you mentioned are all covered with this flatMap method.
See the Either.flatMap documentation for the official docs about it.

How to get an element that caused an exception in Flux?

Let's say I have an array of ids: [9, 8, 7, 6].
I do some processing and one element causes to throw an exception. I want to handle this situation on my own way (let's say log it) and let the other elements go with the flow.
How can I know which one was it? I need to have this element in my onError processing.
Flux.fromArray(myArray)
.flatMap(element -> {
var foo = processMyEl(element);
return anotherProcess(foo); // this returns Mono
})
.onErrorOperator(element -> handleMyError(element)) // this line is what I need
So, what I saw, there's this almost nice .onErrorContinue((error, obj) -> that emits an error and an object.
But this obj is not the element that caused the exception but the object that did so. It happens inside of my processing methods and it doesn't have to be the same type of object every time.
.onErrorReturn(...) - not really what I want
.doOnError(error -> - no information of my element
.onErrorResume(error -> - same as above
there were suggestions that I can create my own Exception and pass there the element and then retrieve it from the exception. But how should I throw the exception?
Should I go with an old way of try catch:
Flux.fromArray(myArray)
.flatMap(el -> {
try {
var foo = processMyEl(el);
return anotherProcess(foo); // this returns Mono
} catch (Exception e) {
return Mono.error(new MyException(el));
}
})
.onErrorOperator(error -> handleMyError(error.getElement()))
It doesn't look well
Edit:
Not only it looks bad, but also doesn't work. The exception is not caught at all and triggers directly doOnTerminate() and stops the whole stream
Update:
Thanks to #JEY I used .onErrorResume() inside flatMap.
I also transformed first method to be a reactive stream by Mono.defer(() -> Mono.just(processMyEl(el))).
Just as a note: using Mono.defer() allows me to use onErrorResume since Mono.just() cannot signal errors.
Final code looks like this:
Flux.fromArray(myArray)
.flatMap(element -> Mono.defer(() -> Mono.just(processMyEl(element)))
.onErrorResume(th -> handleMyError(element, th))
)
.flatMap(foo -> anotherProcess(foo)
.onErrorResume(th -> handleMyError(foo, th)
)
Where:
private Mono<> handleMyError(el, th) {
// handling code
return Mono.empty()
}
As requested by #Kamil I'll add my comments as an answer:
You should just handle the error in the flatMap and return a Mono.empty() to discard it do something like:
Flux.fromArray(myArray)
.flatMap(el -> anotherProcess(processMyEl(el)).onErrorResume(th -> handleError(th, el))
With handle error like:
Mono<Void> handleError(Throwable th, Object element) {
LOG.error("An error occurred on {}", element, th);
return Mono.empty()
}
Or if you want to do something more complex that require async:
Mono<Void> handleError(Throwable th, Object element) {
return doSomethingThaReturnFluxOrMono(element).then();
}
} catch (Exception e) {
throw new MyException(el, e);
}

Preventing RxJava from wrapping my custom exception into composite one

I was given a task to make implementation using RxJava, and safeguard in such way, that if any error happens, it gets wrapped into custom exception.
Problem is, that regardless of what I do RxJavaPlugin decides to wrap my exception into CompositeException even when there is only one. Which fails tests.
I've tried everything I could find on the google all the way up to actually overwriting RxJavaPlugin's global error handler, but it ignores attempted changes.
implementation of function that is supposed to throw it at the moment of writing this post
Single<BigDecimal> summarizeConfirmedTransactions() throws SummarizationException {
try{
Observable<Transaction> observableTransactions = transactions.get()
.doOnError(throwable -> {
Exceptions.propagate(throwable);
});
Observable<Confirmation> observableConfirmations = confirmations.get()
.doOnError(throwable -> {
Exceptions.propagate(throwable);
});
return Observable.zip(observableTransactions, observableConfirmations, (t, c) -> new ConfirmableTransaction(t.transactionId, c.isConfirmed, t.value))
.filter(confirmableTransaction -> confirmableTransaction.isConfirmed)
.map(t -> t.value)
.reduce(BigDecimal::add)
.toSingle()
.doOnError(throwable -> {
Exceptions.propagate(throwable);
});
}catch(Exception e)
{
throw new SummarizationException(e.getMessage());
}
Assertion in test fails because exception ultimately thrown is CompositeException with single exception inside of it. and I am required to have it be of SummarizationException.class
big thanks in advance.
Edit:
On request, here is code used to test the solution. I am not allowed to modify this one.
#Test
public void shouldWrapErrorIntoException() {
final ConfirmedTransactionSummarizer summarizer =
new ConfirmedTransactionSummarizer(ALL_CONFIRMED::transactions, () -> Observable.error(new RuntimeException("Booom")));
summarizer
.summarizeConfirmedTransactions()
.subscribe(testObserver);
testObserver.assertError(SummarizationException.class);
testObserver.assertErrorMessage("Booom");
}
PS. I've asked the giver of the task, he said that "I'm the only one with such problem" and that I should not overcomplicate things and go for easiest solution.... which results in composite exception of 3 exceptions - one of which is my exception wrap and other two are instances of RuntimeException inserted by test code.
Ok, so after a little bit of more digging, and with helpful tip from a friend I've managed to nail down intention of the task:
What I was supposed to do there was:
Single<BigDecimal> summarizeConfirmedTransactions() throws SummarizationException {
Observable<Transaction> observableTransactions = transactions.get();
Observable<Confirmation> observableConfirmations = confirmations.get();
return Observable.zip(observableTransactions, observableConfirmations,
(t, c) -> new ConfirmableTransaction(c.isConfirmed, t.value))
.filter(confirmableTransaction -> confirmableTransaction.isConfirmed)
.map(t -> t.value)
.reduce(BigDecimal::add)
.toSingle()
.onErrorResumeNext(th -> Single.error(new SummarizationException(th.getMessage())));
}
TL:DR I was not supposed to "wrap" errors into thrown exception but wrap them into error response containing exception.
One way to handle this is by using try-catch block in your test, unwraping CompositeException and then asserting caught exception.
fun testSummarizationException() {
try {
summarizeConfirmedTransactions()
} catch (ex: Exception) {
val customException = (ex as? CompositeException)?.exceptions?.get(0)
// assert to make sure thrown exception is of custom type
assert(customException is SummarizationException)
}
}
This is where CompositeException is unwrapped to get custom exception.
val customException = (ex as? CompositeException)?.exceptions?.get(0)
Exception is type-casted to CompositeException if it's permissible. If casting is not allowed for this type, this will return null and fails the test.

How to make JUnit take any Lambda expression

I am using SpringAMQP where I am testing producer method (basically AMQP template) which is like this.
public void send(Message message, Throwable error, String queue, String routingKey) {
this.amqpTemplate.convertAndSend(
RabbitConfiguration.ERROR_EXCHANGE,
RabbitConfiguration.ERROR_ROUTING_KEY,
message,
messageMetaData -> {
messageMetaData.getMessageProperties().getHeaders().put("x-death-reason", error.getMessage());
return messageMetaData;
}
);
}
I am testing this code with following
import static org.hamcrest.Matchers.any;
....
#Test
public void will_create_error_message_if_incorrect_payload_is_given() {
AmqpTemplate amqpTemplate = mock(AmqpTemplate.class);
Throwable throwable = mock(Throwable.class);
when(throwable.getMessage()).thenReturn("first");
when(throwable.getStackTrace()).thenReturn(null);
ErrorMessageProducer errorMessageProducer = new ErrorMessageProducer(amqpTemplate);
Message message = MessageBuilder.withBody("test".getBytes()).build();
verify(amqpTemplate).convertAndSend(
eq(RabbitConfiguration.ERROR_EXCHANGE),
eq(RabbitConfiguration.ERROR_ROUTING_KEY),
any(Message.class),
Mockito.any()
);
}
But I am getting Invalid use of argument matchers! 4 matchers expected, 3 recorded. Is there any way I can test with Lambda or ignore Lambda altogether.
The problem is because you are using wrong any().
verify(amqpTemplate).convertAndSend(
eq(RabbitConfiguration.ERROR_EXCHANGE),
eq(RabbitConfiguration.ERROR_ROUTING_KEY),
any(Message.class),
Mockito.any()
);
Here your 3rd argument using any from org.hamcrest.Matchers.any, however 4th argument uses right Mockito.any(). So 3rd argument isn't detected as a matcher, but is threated like a usual argument.
To check your lambda you should probably use ArgumentCaptor.
ArgumentCaptor<Runnable> argument = ArgumentCaptor.forClass(Runnable.class);
verify(mock).doSomething(any(), argument.capture());
argument.getValue().run();
...verify that lambda called your services...
You can change Runnable to any type of function your lambda actually represents: i.e. Function/Callable.

Java 8: Mandatory checked exceptions handling in lambda expressions. Why mandatory, not optional?

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λ

Categories

Resources