Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WFCOM-71 Port Consumers.close() and Functions.identity() from org.wildfly:wildfly-clustering-common #70

Merged
merged 3 commits into from
May 1, 2023

Conversation

pferraro
Copy link
Contributor

@dmlloyd
Copy link
Member

dmlloyd commented Apr 26, 2023

Since this module has exception-throwing functions, could you do something like this (off the top of my head):

public static <T, E> Consumer<T> exceptionLoggingConsumer(ExceptionConsumer<T, E> consumer) {
    return val -> try {
        consumer.accept(val);
    } catch (Exception e) {
        LOGGER.warn(e, "Consumer threw an exception");
    }
}

And then you can do:

    // ...
    Consumer<AutoCloseable> closingConsumer = exceptionLoggingConsumer(AutoCloseable::close);

@dmlloyd
Copy link
Member

dmlloyd commented Apr 26, 2023

Also, this should be kept in rough parity with smallrye-common, so it'd be good to open a PR there as well. There's a vague long-term goal to move off wildfly-common for most things (if not everything, someday), maybe with forwarding stubs for the mid-term interim.

Comment on lines 44 to 46
public static <T extends R, R> Function<T, R> identityFunction() {
return (Function<T, R>) IDENTITY_FUNCTION;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be better generalized as something like:

public static <T, R, T2 extends T, R2 super R> Function<T2, R2> loosenBoundsOf(Function<T, R> function) {
    return (Function<T2, R2>) function;
}

or something like that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you mean:

public static <T, R extends R2, T2 extends T, R2> Function<T2, R2> loosenBoundsOf(Function<T, R> function) {
    return (Function<T2, R2>) function;
}

In which case, we should consider a different name. While this method can loosen the bounds of the return type, it can also constrain the bounds of the argument (or both).
e.g.

Function<Number, Number> function = Function.identity();
Function<Integer, Object> result = loosenBoundsOf(function);

Maybe just name it "cast"?
Also, this suggests analogous methods for Supplier, Consumer, BiFunction, exception variants, etc.

@pferraro
Copy link
Contributor Author

pferraro commented Apr 26, 2023

Creating a generalized exceptionLoggingConsumer(...) makes sense, I think, and also suggests analogous methods for ExceptionBiConsumer, ExceptionObjIntConsumer, etc.

@pferraro
Copy link
Contributor Author

Re: smallrye-common; I can do that - as soon as this passes muster.

Add quiet(...) methods to convert from an ExceptionConsumer -> Consumer, ExceptionBiConsumer -> BiConsumer, etc.
Add exception consumer methods for logging and RuntimeException wrapping.
@pferraro
Copy link
Contributor Author

@dmlloyd Well, this got out of hand quickly...

Re: closingConsumer():

I've generalized the original closingConsumer(), by generalizing your suggestion a bit further, adding a number of "quite" methods to convert exception-based consumers to standard consumers.
e.g.
Now this:

Consumer<InputStream> streamCloser = Functions.closingConsumer();

is equivalent to:

Consumer<InputStream> streamCloser = Functions.quiet(InputStream::close, exceptionLoggingConsumer());

If, instead, I wanted close() wrapped as an UncheckedIOException, I can do:

Consumer<InputStream> streamCloser = Functions.quiet(InputStream::close, runtimeExceptionThrowingConsumer(UncheckedIOException::new));

runtimeExceptionThrowingConsumer(...) can also be used to convert an ExceptionConsumer<T, RuntimeException> to a Consumer:

ExceptionConsumer<Throwable, NullPointerException> consumer = Throwable::printStackTrace;
Consumer<Throwable> result = Functions.quiet(consumer, runtimeExceptionThrowingConsumer(Function.identity()));

Re: identityFunction()

I've created generalized function for restricting parameter/exception types and/or relaxing return types:
e.g.

ExceptionFunction<Number, Number, NumberFormatException> function = v -> v;
ExceptionFunction<Integer, Object, Exception> castFunction = Functions.cast(function);

Let me know what you think - or if you have better suggesting for these method names.

@dmlloyd
Copy link
Member

dmlloyd commented May 1, 2023

I think this looks good and these will be very useful. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants