In my opinion, Java 8 and later versions (actually 9 and 10) lack of a piece to efficiently use Stream and other monads. Java does not have any kind of Try monad to handle errors during monad composition.
Why? Initially, I thought that was a lack of only the version 8, but I do not find any JEP to introduce it in the JDK.
Something like the following could be a starting point.
public class Try<T> {
private T value;
private Exception exception;
private Try(Supplier<T> supplier) {
try {
this.value = supplier.get();
} catch (Exception ) {
this.exception = ex;
}
}
Optional<T> toOptional() {
return Optional.ofNullable(value);
}
public static <T> Try<T> of(Supplier<T> supplier) {
return new Try<>(supplier);
}
// Some other interesting methods...
}
Maybe not anyone uses reactive streams, but during a stream transformation, you need some smart way to collect exceptions, without breaking the whole stream execution.
stream
.map(info -> {
// Code that can rise an exception
// Without the Try monad is tedious to handle exceptions!
})
.filter(/* something */)
.to(/* somewhere */)
Can anyone explain me why? Is it related to some other specification lack?
Thanks to all.
Related
I was going through the resilience4j code to find out how they implement the decorators, I can see Supplier/Consumer functional interfaces. i am still trying to understand on how to utilize these interfaces while coding. My question is based on this method,
static <T> Supplier<Future<T>> decorateFuture(Bulkhead bulkhead, Supplier<Future<T>> supplier) {
return () -> {
if (!bulkhead.tryAcquirePermission()) {
final CompletableFuture<T> promise = new CompletableFuture<>();
promise.completeExceptionally(BulkheadFullException.createBulkheadFullException(bulkhead));
return promise;
}
try {
return new BulkheadFuture<>(bulkhead, supplier.get());
} catch (Throwable e) {
bulkhead.onComplete();
throw e;
}
};
Have couple of questions,
Is it returning a Supplier<Future> because of its defined as a lambda?
How do these decorators are constructed, please can someone provide a simple example,
Supplier<String> decoratedSupplier = Bulkhead
.decorateSupplier(bulkhead, () -> "This can be any method which returns: 'Hello");
I have the following interface with two implementations:
public interface Parser {
void parse();
boolean canParse(String message);
}
class StackParser implements Parser {
public void parse(){
System.out.println("Parsing stackoverflow");
}
public boolean canParse(String message){
return message.equals("stackoverflow");
}
}
class YoutubeParser implements Parser {
public void parse() {
System.out.println("Parsing youtube");
}
public boolean canParse(String message) {
return message.equals("youtube");
}
}
I go to check incoming message and parse "stackoverflow" or "youtube":
public class Main {
private List<Parser> parsers;
public static void main(String[] args) {
new Main().doSomething("youtube");
}
void doSomething(String message){
parsers.stream()
.filter(p -> p.canParse(message))
.forEach(p -> p.parse());
}
}
Okay, pretty good. But what if message is not "stackoverflow" or "youtube"? App will be silent, but I want to send another default message if no matches were found, like "I can't parse this web!".
I know that will not works (even compile), but it's also should print "I can't parse this web" only one time, not for every false condition.
parsers.stream()
.filter(p -> {
if (p.canParse(message) == false) {
System.out.println("I can't parse it!");
}
})
.forEach(p -> p.parse());
How can I do it?
This is a perfect example of when to use the Optional#orElse or the Optional#orElseThrow method(s). You want to check if some condition is met so you filter, trying to return a single result. If one does not exist, some other condition is true and should be returned.
try {
Parser parser = parsers.stream()
.filter(p -> p.canParse(message))
.findAny()
.orElseThrow(NoParserFoundException::new);
// parser found, never null
parser.parse();
} catch (NoParserFoundException exception) {
// cannot find parser, tell end-user
}
In case only one parser can parse the message at a time you could add a default parser:
class DefaultParser implements Parser {
public void parse() {
System.out.println("Could not parse");
}
public boolean canParse(String message) {
return true;
}
}
And then use it via
// make sure the `DefaultParser` is the last parser in the `parsers`
parsers.stream().filter(p -> p.canParse(message)).findFirst().get().parse();
or alternatively drop the DefaultParser and just do
Optional<Parser> parser = parsers.stream().filter(p -> p.canParse(message)).findFirst();
if (parser.isPresent()) {
parser.get().parse();
} else {
// handle it
}
You can use simply a forEach if-else inside
parsers.forEach(p -> {
if (!p.canParse(message)) {
System.out.println("I can't parse it!");
} else {
p.parse();
}
});
That's a pretty interesting question, which fortunately I had to face some time ago.
Mi approach consisted on declaring a list of Supplier<T> which would be iterated only if there's and exception thrown (the intention of this approach was to retrieve data from DB based on the parameters given, so I would be able to search by id or by an instance).
import java.util.function.Supplier;
public class AbstractFacadeUtil {
public <R> R tryOr(Supplier<R>...fns) {
R result = null;
boolean success = false;
int i = 0;
while (!success && i < fns.length) {
Supplier<R> fn = fns[i++];
try {
result = fn.get();
success = true;
} catch (Exception e) {
}
}
if (!success) {
throw new RuntimeException(new Exception(String.format("[%s] Couldn't find a successful method to apply\"", this.getClass())));
}
return result;
}
}
Some notes:
I'd used Supplier<T> because it's body didn't contain anything that would throw an undeclared exception which, otherwise, would be needed to use Callable<T> instead.
Yeah, could have given it a better name though.
Maybe an Iterator<T> would make that piece of code more understandable and clean.
In your specific case, I'd use Jason's approach by adding a Supplier<T> at the end of the list that would throw an NoParserFoundException
[EDIT]
Also, you should iterate the List<Supplier<T>> or List<Callable<T>> wheter the Parser can't parse and it throws an CantParseException.
So, as you see, exceptions can help a lot even I'm not sure this would be the most efficient or expert approach.
Hope it helps you.
[EDIT2]
This is an example of how I implemented the solution given above.
Ok, I'm gonna say it. Look at every solution posted - what do you think? Are they neat, clean code that you would expect from functional approach?
Nope, why? Because the design is wrong, it doesn't fit functional approach.
Fix the design:
get rid of void return type (brr)
don't overuse methods like canDoSomething (treat them like isPresent in Optional - it's there for extreme cases, mostly technical, not business code)
look into VAVR (or similar library) - classes like Try, Either etc.
Solution will come naturally then and in every case - not only this specific one you posted here.
In a Spring application I tend to take the request body in a controller method and want to pipe it fluently through multiple method calls (returning different types along the way) such as in the following (simplified) example:
public ResponseEntity<FooDto> postFoo(#RequestBody final FooDto requestBody) {
return Optional.of(requestBody) // Optional<FooDto>
.map(mapper::fromDto) // Optional<FooEntity>
.map(service::insertEntity) // Optional<FooEntity>
.map(mapper::fromEntity) // Optional<FooDto>
.map(dto -> ResponseEntity.created(/* ... */).body(dto).build()) // Optional<ResponseEntity<FooDto>>
.orElseThrow(IllegalStateException::new);
}
As you can see I am tempted to apply some FP patterns but the Optional class isn't really suited to do so since the "optionality" implied is artificial and the underlying object of interest should never be empty in the first place. Therefore the final exception won't (hopefully) ever be thrown and alternatively just calling Optional::get isn't really a great option either since Sonarlint complains about an unchecked get call and rightfully so.
Is there any idiomatic way available, maybe even in conjunction with vavr or other FP libraries, to express such a chain of methods better than with such artifical Optional constructs? Otherwise I might have to refrain from doing so and revert back to a classic imperative approach with a dozen of variables.
EDIT: The way I attempt to use Optional easily gets out of hand if working with methods that return Either<ErrorReason, Optional<FooEntity>> which makes this an Optional<Either<ErrorReason, Optional<FooEntity>>> ending up not legible anymore.
The cleanest way to perform what you're looking for is to restore to the imperative style such as:
public ResponseEntity<FooDto> postFoo(final FooDto requestBody) {
final FooEntity fooEntity = fromDto(requestBody);
final FooEntity updatedEntity = insertEntity(fooEntity); // should be void?
final FooDto responseDto = fromEntity(updatedEntity);
return ResponseEntity.created(/* ... */)
.body(responseDto)
.build();
}
I agree with Naman that an imperative style is probably the cleanest way in this case.
If you really really want to do some Optional style like flow you can create your own class
public final class Value<T> {
private final T value;
// Private constructor to force usage of static construction
private Value(T value) {
this.value = value;
}
// Static constructor Optional style
public static <T> Value<T> of(T value) {
return new Value<>(value);
}
public <R> Value<R> map(Function<? super T, ? extends R> mapper) {
return new Value<>(mapper.apply(this.value));
}
// method to unwrap value
public T get() {
return value;
}
}
Then you would use it like
public ResponseEntity<FooDto> postFoo(#RequestBody final FooDto requestBody) {
return Value.of(requestBody) // Value<FooDto>
.map(mapper::fromDto) // Value<FooEntity>
.map(service::insertEntity) // Value<FooEntity>
.map(mapper::fromEntity) // Value<FooDto>
.map(dto -> ResponseEntity.created(/* ... */).body(dto).build()) // Value<ResponseEntity<FooDto>>
.get();
}
Again, I highly discourage this solution and I would just opt for using imperative style.
How can I check if a stream instance has been consumed or not (meaning having called a terminal operation such that any further call to a terminal operation may fail with IllegalStateException: stream has already been operated upon or closed.?
Ideally I want a method that does not consume the stream if it has not yet been consumed, and that returns a boolean false if the stream has been consumed without catching an IllegalStateException from a stream method (because using Exceptions for control flow is expensive and error prone, in particular when using standard Exceptions).
A method similar to hasNext() in Iterator in the exception throwing and boolean return behavior (though without the contract to next()).
Example:
public void consume(java.util.function.Consumer<Stream<?>> consumer, Stream<?> stream) {
consumer.accept(stream);
// defensive programming, check state
if (...) {
throw new IllegalStateException("consumer must call terminal operation on stream");
}
}
The goal is to fail early if client code calls this method without consuming the stream.
It seems there is no method to do that and I'd have to add a try-catch block calling any terminal operation like iterator(), catch an exception and throw a new one.
An acceptable answer can also be "No solution exists" with a good justification of why the specification could not add such a method (if a good justification exists). It seems that the JDK streams usually have this snippets at the start of their terminal methods:
// in AbstractPipeline.java
if (linkedOrConsumed)
throw new IllegalStateException(MSG_STREAM_LINKED);
So for those streams, an implementation of such a method would not seem that difficult.
Taking into consideration that spliterator (for example) is a terminal operation, you can simply create a method like:
private static <T> Optional<Stream<T>> isConsumed(Stream<T> stream) {
Spliterator<T> spliterator;
try {
spliterator = stream.spliterator();
} catch (IllegalStateException ise) {
return Optional.empty();
}
return Optional.of(StreamSupport.stream(
() -> spliterator,
spliterator.characteristics(),
stream.isParallel()));
}
I don't know of a better way to do it... And usage would be:
Stream<Integer> ints = Stream.of(1, 2, 3, 4)
.filter(x -> x < 3);
YourClass.isConsumed(ints)
.ifPresent(x -> x.forEachOrdered(System.out::println));
Since I don't think there is a practical reason to return an already consumed Stream, I am returning Optional.empty() instead.
One solution could be to add an intermediate operation (e.g. filter()) to the stream before passing it to the consumer. In that operation you do nothing but saving the state, that the operation was called (e.g. with an AtomicBoolean):
public <T> void consume(Consumer<Stream<T>> consumer, Stream<T> stream) {
AtomicBoolean consumed = new AtomicBoolean(false);
consumer.accept(stream.filter(i -> {
consumed.set(true);
return true;
}));
if (!consumed.get()) {
throw new IllegalStateException("consumer must call terminal operation on stream");
}
}
Side Note: Do not use peek() for this, because it is not called with short-circuiting terminal operations (like findAny()).
Here is a standalone compilable solution that uses a delegating custom Spliterator<T> implementation + an AtomicBoolean to accomplish what you seek without losing thread-safety or affecting the parallelism of a Stream<T>.
The main entry is the Stream<T> track(Stream<T> input, Consumer<Stream<T>> callback) function - you can do whatever you want in the callback function. I first tinkered with a delegating Stream<T> implementation but it's just too big an interface to delegate without any issues (see my code comment, even Spliterator<T> has its caveats when delegating):
import java.util.Spliterator;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
class StackOverflowQuestion56927548Scratch {
private static class TrackingSpliterator<T> implements Spliterator<T> {
private final AtomicBoolean tracker;
private final Spliterator<T> delegate;
private final Runnable callback;
public TrackingSpliterator(Stream<T> forStream, Runnable callback) {
this(new AtomicBoolean(true), forStream.spliterator(), callback);
}
private TrackingSpliterator(
AtomicBoolean tracker,
Spliterator<T> delegate,
Runnable callback
) {
this.tracker = tracker;
this.delegate = delegate;
this.callback = callback;
}
#Override
public boolean tryAdvance(Consumer<? super T> action) {
boolean advanced = delegate.tryAdvance(action);
if(tracker.compareAndSet(true, false)) {
callback.run();
}
return advanced;
}
#Override
public Spliterator<T> trySplit() {
Spliterator<T> split = this.delegate.trySplit();
//may return null according to JavaDoc
if(split == null) {
return null;
}
return new TrackingSpliterator<>(tracker, split, callback);
}
#Override
public long estimateSize() {
return delegate.estimateSize();
}
#Override
public int characteristics() {
return delegate.characteristics();
}
}
public static <T> Stream<T> track(Stream<T> input, Consumer<Stream<T>> callback) {
return StreamSupport.stream(
new TrackingSpliterator<>(input, () -> callback.accept(input)),
input.isParallel()
);
}
public static void main(String[] args) {
//some big stream to show it works correctly when parallelized
Stream<Integer> stream = IntStream.range(0, 100000000)
.mapToObj(Integer::valueOf)
.parallel();
Stream<Integer> trackedStream = track(stream, s -> System.out.println("consume"));
//dummy consume
System.out.println(trackedStream.anyMatch(i -> i.equals(-1)));
}
}
Just return the stream of the track function, maybe adapt the callback parameters type (you probably don't need to pass the stream) and you are good to go.
Please note that this implementation only tracks when the stream is actually consumed, calling .count() on a Stream that was produced by e.g. IntStream.range(0,1000) (without any filter steps etc.) will not consume the stream but return the underlying known length of the stream via Spliterator<T>.estimateSize()!
Or is there a better way to do this that I'm missing? I'd like to create a stream based on a Supplier (which are normally infinite), but have the stream terminate when the supplier returns null. I made this myself, but it seems like a fair amount of work to accomplish a pretty simple concept.
public class NullTerminatedStreamFactory {
static int characteristics = Spliterator.ORDERED | Spliterator.DISTINCT;
public static<T> Stream<T> makeNullTerminatedStream(Supplier<T> supplier) {
return StreamSupport.stream(new NullTerminatedSpliteratorFromSupplier<>(supplier, Long.MAX_VALUE, characteristics), false);
}
static class NullTerminatedSpliteratorFromSupplier<T> extends Spliterators.AbstractSpliterator<T> {
public NullTerminatedSpliteratorFromSupplier(Supplier<T> supplier, long est, int additionalCharacteristics) {
super(est, additionalCharacteristics);
this.supplier = supplier;
}
public Supplier<T> supplier;
#Override
public boolean tryAdvance(Consumer<? super T> action) {
T next = supplier.get();
if (next != null) {
action.accept(next);
return true;
}
return false;
}
}
}
For the record, I'm using it like this, to basically create a Stream from a BlockingQueue:
NullTerminatedStreamFactory.makeNullTerminatedStream(() -> {
try {
BlockingQueue<Message> queue = getBlockingQueue();
return queue.poll(1, TimeUnit.SECONDS);
} catch (Exception e) {
log.error("Exception while trying to get message from queue", e);
}
return null;
});
You've already found a perfectly valid hand-made implementation.
As mentioned in the comments, Java 9 seems to add a takeWhile(Predicate) method. Until then, you could use a third-party library that implements something like takeWhile():
jOOλ
jOOλ has limitWhile(), which does the same thing:
Seq.generate(supplier).limitWhile(Objects::nonNull);
(disclaimer, I work for the company behind jOOλ)
Javaslang
Javaslang implemented their own Stream class, which is inspired by the Scala collections, and thus has takeWhile()
Stream.gen(supplier).takeWhile(Objects::nonNull);
Functional Java
Functional Java also ship with their own Stream implementation, that has a takeWhile() method:
Stream.fromFunction(i -> supplier.get()).takeWhile(o -> o != null);