Skip to content

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

Merged
dmlloyd merged 3 commits intowildfly:mainfrom
pferraro:master
May 1, 2023
Merged

WFCOM-71 Port Consumers.close() and Functions.identity() from org.wildfly:wildfly-clustering-common#70
dmlloyd merged 3 commits intowildfly:mainfrom
pferraro:master

Conversation

@pferraro
Copy link
Copy Markdown
Contributor

@dmlloyd
Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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