I have defined a function in Kotlin:
fun convertExceptionToEmpty(requestFunc: () -> List<Widget>): Stream<Widget> {
try {
return requestFunc().stream()
} catch (th: Throwable) {
// Log the exception...
return Stream.empty()
}
}
I have defined a Java method with this signature:
List<Widget> getStaticWidgets() throws IOException;
I attempt to compose them like so:
Stream<Widget> widgets = convertExceptionToEmpty(() -> getStaticWidgets())
When I compile I get this error:
Error:(ln, col) java: unreported exception java.io.IOException; must be caught or declared to be thrown
How do I define my function parameters to accept a function that throws?
The problem is that Java has checked exceptions but Kotlin does not. The requestFunc parameter type () -> List<Widget> will be mapped to the functional interface Function0<List<Widget>> but the operator invoke doesn't throw a checked exception in Kotlin code.
So you can't call the getStaticWidgets() in lambda expression since it throws a IOException which is a checked exception in Java.
Since you control both the Kotlin and Java code, the simplest solution is to change the parameter type () -> List<Widget> to Callable<List<Widget>>, for example:
// change the parameter type to `Callable` ---v
fun convertExceptionToEmpty(requestFunc: Callable<List<Widget>>): Stream<Widget> {
try {
// v--- get the `List<Widget>` from `Callable`
return requestFunc.call().stream()
} catch (th: Throwable) {
return Stream.empty()
}
}
Then you can use Method Reference Expression in Java8 as further, for example:
Stream<Widget> widgets = convertExceptionToEmpty(this::getStaticWidgets);
//OR if `getStaticWidgets` is static `T` is the class belong to
// v
Stream<Widget> widgets = convertExceptionToEmpty(T::getStaticWidgets);
I'm afraid there's nothing you can do but catch that exception :
Stream<Integer> widgets = convertExceptionToEmpty(() -> {
try {
return getStaticWidgets();
} catch (IOException e) {
e.printStackTrace();
}
return null;
});
Related
It is difficult to find any clues for the topic. All I could find is questions about converting one functional interface to another and some articles on type casting in Java. Not what I was looking for.
This question is about converting lambda → Method and I want the opposite, to convert Method to any functional interface, for example, to Consumer.
The way I found is to create a lambda adapter around the Method#invoke method:
public void registerCallbacks(final Object annotated) {
Class clazz = annotated.getClass();
for (Method method : clazz.getDeclaredMethods()) {
if (method.isAnnotationPresent(Callback.class)) {
Callback registration = method.getAnnotation(Callback.class);
List<String> warnings = new ArrayList<>(3);
if (!Modifier.isPublic(method.getModifiers()))
warnings.add(String.format("Method %s must be public", method));
if (method.getParameterCount() != 1)
warnings.add(String.format("Method %s must consume only one argument", method));
if (method.getParameterCount() == 1 && !method.getParameterTypes()[0].equals(Integer.class))
warnings.add(String.format("Method %s must consume %s", method, Integer.class));
if (!warnings.isEmpty()) {
warnings.forEach(log::warn);
continue;
}
CALLBACKS_MAPPER.registerCallback((param) -> {
try {
method.invoke(annotated, param);
} catch (IllegalAccessException | InvocationTargetException e) {
// Should not happen due to checks before.
log.warn(String.format("Could not invoke %s on %s with %s", method, annotated, param), e);
}
});
log.info("Registered {} as a callback", method);
}
}
}
However I want to avoid writing
CALLBACKS_MAPPER.registerCallback((param) -> {
try {
method.invoke(annotated, param);
} catch (IllegalAccessException | InvocationTargetException e) {
// Should not happen due to checks before.
log.warn(String.format("Could not invoke %s on %s with %s", method, annotated, param), e);
}
});
in favor of something simpler, like
CALLBACKS_MAPPER.registerCallback(SomeApacheLib.methodToFunction(annotated, method));
➥ So, is there a way to map old Java 1.1 reflection library to newer Java 8 functional interfaces, or it is me being stupid and the abovementioned solution with lambda is fine as it is?
If you're content with using reflection under the hood, just don't like the try/catch around the invoke, you can just make a simple utility function like:
public static <T> Consumer<T> toConsumer(Object annotated, Method m) {
return param -> {
try {
m.invoke(annotated, param);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};
}
And that gives you exactly the syntax you wanted:
CALLBACKS_MAPPER.registerCallback(toConsumer(annotated, method));
But if you want to actually avoid reflection altogether, you can use LambdaMetafactory to create a Consumer:
static Consumer<String> toConsumer(MethodHandles.Lookup lookup, Object annotated, Method method) throws Throwable {
MethodType consumeString = MethodType.methodType(void.class, String.class);
MethodHandle handle = lookup.unreflect(method);
final CallSite site = LambdaMetafactory.metafactory(lookup, "accept",
MethodType.methodType(Consumer.class, annotated.getClass()),
consumeString.changeParameterType(0, Object.class),
handle,
consumeString);
return (Consumer<String>) site.getTarget().invoke(annotated);
}
Change String to whatever your callbacks are expected to accept. And then:
CALLBACKS_MAPPER.registerCallback(toConsumer(MethodHandles.lookup(), annotated, method));
Of course, the only proper solution here is that you refactor your code to use a known callback interface on which you can normally call a defined method, instead of passing Methods around.
I have some wrapper class for JDBC statement execution with many methods like following:
public ResultSet executeQuery(String sql) {
try (Statement statement = this.connection.createStatement()) {
return statement.executeQuery(sql);
} catch (SQLException e) {
throw new RuntimeException("My custom statement execution failure", e);
}
}
public int executeUpdate(String sql) {
try (Statement statement = this.connection.createStatement()) {
return statement.executeUpdate(sql);
} catch (SQLException e) {
throw new RuntimeException("My custom statement execution failure", e);
}
}
...
So there are a lot of methods that are different only with 1) return type and 2) actual delegated method.
I would like to pass executable call in Ruby's lambda fashion, to reduce boilerplate code to something like this:
public Boolean executeQuery(String sql) {
return wrapException(s -> {s.executeQuery(sql)});
}
private <T> wrapException(Function<Statement, <T>> query)throws Exception {
try (Statement statement = this.connection.createStatement()) {
return query.apply(statement);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Two things I currently fail to wrap my head around are:
how to preserve generic return type of the wrappedQuery function
s.executeQuerty(sql) still complains about unhandled SQLException,
so effectively I'm not able to wrap all exception handling away
Any ideas?
Function<Statement, <T>> is not valid syntax. It should be just Function<Statement, T>. Apparently, you are confusing the declaration of a type parameter, like at the method’s beginning (<T>) with the use of the type parameter, which should be a plain name, like T. Note that, likely for the same reason, your method lacks a return type. There should be a <T> to declare the type parameter, followed by a T to declare the return type before the method’s name.
Your method wrapException still declares throws Exception which is even worse than the JDBC methods which only declare to throw SQLException. This contradicts the whole intention.
A value returning lambda expression should either, follow the expression syntax,
like s -> s.executeQuery(sql), or contain a return statement, e.g. s -> { return s.executeQuery(sql); }. Your expression s -> {s.executeQuery(sql)} is an incomplete (missing semicolon) statement syntax without a return. Also, you are declaring a Boolean return type despite that executeQuery returns a ResultSet.
The functional interface java.util.function.Function declares the function method apply which does not declare any checked exceptions, therefore you can’t implement it via a lambda expression which could throw checked exceptions like SQLException. So for your use case, you need a different functional interface.
You may make the exception type generic to allow your custom functional interface to be reused at other places where you need a Function that may throw a particular exception. E.g.
public interface ThrowingFunction<T,R,E extends Exception> {
R apply(T input) throws E;
}
with this, you may declare
public ResultSet executeQuery(String sql) {
return wrapException(s -> s.executeQuery(sql));
}
public int executeUpdate(String sql) {
return wrapException(s -> s.executeUpdate(sql));
}
private <T> T wrapException(ThrowingFunction<Statement, T, SQLException> operation) {
try(Statement statement = this.connection.createStatement()) {
return operation.apply(statement);
} catch(SQLException e) {
throw new RuntimeException(e);
}
}
But note that there is a general problem independent from the Generics/lambda usage that applies to your original code as well:
Statement.close()
Note: When a Statement object is closed, its current ResultSet object, if one exists, is also closed.
The whole purpose of the try(…) statement is to ensure that the resource will be closed immediately when leaving the block, so returning a ResultSet from there is pointless. (This does not apply to the executeUpdate though). One way to fix this, would be to pass a function to process the ResultSet right within the block.
public <R> R executeQuery(String sql, ThrowingFunction<ResultSet,R,SQLException> op) {
return wrapException(s -> op.apply(s.executeQuery(sql)));
}
This allows the function to return an arbitrary value not depending on the ResultSet anymore, e.g.
String value = executeQuery("SELECT STRING_COL FROM SOME_TABLE WHERE ID=42",
rs -> rs.next()? rs.getString(1): null);
int max = executeQuery("SELECT MAX(INTVAL_COL) FROM SOME_TABLE",
rs -> rs.next()? rs.getInt(1): -1);
Is there a better way to assert that a method throws an exception in JUnit 5?
Currently, I have to use an #Rule in order to verify that my test throws an exception, but this doesn't work for the cases where I expect multiple methods to throw exceptions in my test.
You can use assertThrows(), which allows you to test multiple exceptions within the same test. With support for lambdas in Java 8, this is the canonical way to test for exceptions in JUnit.
Per the JUnit docs:
import static org.junit.jupiter.api.Assertions.assertThrows;
#Test
void exceptionTesting() {
MyException thrown = assertThrows(
MyException.class,
() -> myObject.doThing(),
"Expected doThing() to throw, but it didn't"
);
assertTrue(thrown.getMessage().contentEquals("Stuff"));
}
In Java 8 and JUnit 5 (Jupiter) we can assert for exceptions as follows.
Using org.junit.jupiter.api.Assertions.assertThrows
public static < T extends Throwable > T assertThrows(Class< T > expectedType,
Executable executable)
Asserts that execution of the supplied executable throws an exception of the expectedType and returns the exception.
If no exception is thrown, or if an exception of a different type is thrown, this method will fail.
If you do not want to perform additional checks on the exception instance, simply ignore the return value.
#Test
public void itShouldThrowNullPointerExceptionWhenBlahBlah() {
assertThrows(NullPointerException.class,
()->{
//do whatever you want to do here
//ex : objectName.thisMethodShoulThrowNullPointerExceptionForNullParameter(null);
});
}
That approach will use the Functional Interface Executable in org.junit.jupiter.api.
Refer :
http://junit.org/junit5/docs/current/user-guide/#writing-tests-assertions
http://junit.org/junit5/docs/5.0.0-M2/api/org/junit/jupiter/api/Executable.html
http://junit.org/junit5/docs/5.0.0-M4/api/org/junit/jupiter/api/Assertions.html#assertThrows-java.lang.Class-org.junit.jupiter.api.function.Executable-
They've changed it in JUnit 5 (expected: InvalidArgumentException, actual: invoked method) and code looks like this one:
#Test
public void wrongInput() {
Throwable exception = assertThrows(InvalidArgumentException.class,
()->{objectName.yourMethod("WRONG");} );
}
Now Junit5 provides a way to assert the exceptions
You can test both general exceptions and customized exceptions
A general exception scenario:
ExpectGeneralException.java
public void validateParameters(Integer param ) {
if (param == null) {
throw new NullPointerException("Null parameters are not allowed");
}
}
ExpectGeneralExceptionTest.java
#Test
#DisplayName("Test assert NullPointerException")
void testGeneralException(TestInfo testInfo) {
final ExpectGeneralException generalEx = new ExpectGeneralException();
NullPointerException exception = assertThrows(NullPointerException.class, () -> {
generalEx.validateParameters(null);
});
assertEquals("Null parameters are not allowed", exception.getMessage());
}
You can find a sample to test CustomException here : assert exception code sample
ExpectCustomException.java
public String constructErrorMessage(String... args) throws InvalidParameterCountException {
if(args.length!=3) {
throw new InvalidParameterCountException("Invalid parametercount: expected=3, passed="+args.length);
}else {
String message = "";
for(String arg: args) {
message += arg;
}
return message;
}
}
ExpectCustomExceptionTest.java
#Test
#DisplayName("Test assert exception")
void testCustomException(TestInfo testInfo) {
final ExpectCustomException expectEx = new ExpectCustomException();
InvalidParameterCountException exception = assertThrows(InvalidParameterCountException.class, () -> {
expectEx.constructErrorMessage("sample ","error");
});
assertEquals("Invalid parametercount: expected=3, passed=2", exception.getMessage());
}
TL;DR: If you are on JUnit 5.8.0+ version, you can use assertThrowsExactly() instead of assertThrows() to match the exact exception type.
assertThrowsExactly(FileNotFoundException.class, () -> service.blah());
You can use assertThrows(), But with assertThrows your assertion will pass even if the thrown exception is of child type.
This is because, JUnit 5 checks exception type by calling Class.isIntance(..), Class.isInstance(..) will return true even if the thrown exception is of a child type.
The workaround for this is to assert on Class:
Throwable throwable = assertThrows(Throwable.class, () -> {
service.readFile("sampleFile.txt");
});
assertEquals(FileNotFoundException.class, throwable.getClass());
You can use assertThrows(). My example is taken from the docs http://junit.org/junit5/docs/current/user-guide/
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
....
#Test
void exceptionTesting() {
Throwable exception = assertThrows(IllegalArgumentException.class, () -> {
throw new IllegalArgumentException("a message");
});
assertEquals("a message", exception.getMessage());
}
I think this is an even simpler example
List<String> emptyList = new ArrayList<>();
Optional<String> opt2 = emptyList.stream().findFirst();
assertThrows(NoSuchElementException.class, () -> opt2.get());
Calling get() on an optional containing an empty ArrayList will throw a NoSuchElementException. assertThrows declares the expected exception and provides a lambda supplier (takes no arguments and returns a value).
Thanks to #prime for his answer which I hopefully elaborated on.
An even simpler one liner. No lambda expressions or curly braces required for this example using Java 8 and JUnit 5
import static org.junit.jupiter.api.Assertions.assertThrows;
#Test
void exceptionTesting() {
assertThrows(MyException.class, myStackObject::doStackAction, "custom message if assertion fails...");
// note, no parenthesis on doStackAction ex ::pop NOT ::pop()
}
Actually I think there is a error in the documentation for this particular example. The method that is intended is expectThrows
public static void assertThrows(
public static <T extends Throwable> T expectThrows(
My solution:
protected <T extends Throwable> void assertExpectedException(ThrowingRunnable methodExpectedToFail, Class<T> expectedThrowableClass,
String expectedMessage) {
T exception = assertThrows(expectedThrowableClass, methodExpectedToFail);
assertEquals(expectedMessage, exception.getMessage());
}
And you can call it like this:
assertExpectedException(() -> {
carService.findById(id);
}, IllegalArgumentException.class, "invalid id");
This is what I do when testing to make sure an exception has been thrown
//when
final var tripConsumer = new BusTripConsumer(inputStream);
final Executable executable = () -> tripConsumer.deserialiseTripData();
//then
assertThrows(IllegalArgumentException.class, executable);
Here is an easy way.
#Test
void exceptionTest() {
try{
model.someMethod("invalidInput");
fail("Exception Expected!");
}
catch(SpecificException e){
assertTrue(true);
}
catch(Exception e){
fail("wrong exception thrown");
}
}
It only succeeds when the Exception you expect is thrown.
How can I iterate over the attributes of an object, with the attribute names provided in a list/array - NOT all attributes, like using reflection & getDeclaredFields().
public class MyClass
{
public type1 att1;
public type2 att2;
public type3 att3;
public MyClass(
att1="helo";
att2="bye";
att3="morning";
);
...
public void function()
{
String myStrings[];
myStrings = new String[] { "att2", "att3" };
MyClass myobject = new MyClass();
for(var in myStrings)
{
System.out.println(var);
System.out.println(myobject.var);
System.out.println();
}
}
}
Your question is somewhat ambiguous about using reflection. If you are OK with reflection, but want specific fields only without iterating over getDeclaredFields(), then the following code should work for you:
for (String var : myStrings) {
Field field = MyClass.class.getDeclaredField(var);
field.setAccessible(true);
System.out.println(var);
System.out.println(field.get(myObject));
System.out.println();
}
Note that this code works for private fields, too. Also, keep in mind that you'll have to handle exception associated with the reflection calls.
UPDATE: Exceptions thrown in this code.
MyClass.class.getDeclaredField(var) declares a checked NoSuchFieldException. You must handle it because obviously there is no mechanism to make sure that the fields in myString match an actual implementation of MyClass.
field.get(myObject) throws a checked IllegalAccessException if the field is inaccessible. Which it should not be because of field.setAccessible(true), but you still have to catch or re-throw the exception.
There are also unchecked exceptions you may want to handle. See the javadoc for details
java.lang.Class.getDeclaredField(String)
java.lang.reflect.AccessibleObject.setAccessible(boolean) inherited by java.lang.reflect.Field
java.lang.reflect.Field.get(Object)
You probably want to use some technology that builds on top of JavaBeans / BeanInfo. Apache Commons / BeanUtils is a good starting point here.
Please refer to this previous answer of mine for more info:
https://stackoverflow.com/a/5856982/342852
But if you just want to use fields, not bean properties, here's a Java 8 method to do so:
public static Map<String, Object> getFieldProperties(Object o, Collection<String> fields) {
Class<?> type = o.getClass();
return fields.stream().map(n -> {
try {
return type.getDeclaredField(n);
} catch (NoSuchFieldException e) {
throw new IllegalStateException(e);
}
}).collect(Collectors
.toMap(
(Function<Field, String>) Field::getName,
(Function<Field, Object>) field -> {
try {
field.setAccessible(true);
return field.get(o);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}));
}
Unfortunately the checked exceptions make this more verbose than it would need to be.
I like new Java8 StreamAPI and want use it not only for one file.
As usually, I use this code:
Stream<String> lines = Files.lines(Paths.get("/somepathtofile"));
But how read two file in one stream if it possibly?
Without any extra helper functions or outside libraries, the easiest is:
Stream<String> lines1 = Files.lines(Paths.get("/somepathtofile"));
Stream<String> lines2 = Files.lines(Paths.get("/somepathtoanotherfile"));
Stream.concat(lines1, lines)
.filter(...)
.forEach(...);
If Files.lines hadn't been declared to throw a checked exception, you'd be able to do
Stream.of("/file1", "/file2")
.map(Paths::get)
.flatMap(Files::lines)....
But, alas, we can't do that. There are several workarounds. One is to make your own version of Files.lines that calls the standard one, catches IOException and rethrows as an UncheckedIOException. Another approach is a more general way to make functions out of methods that throw checked exceptions. It would look something like this:
#FunctionalInterface
public interface ThrowingFunction<T,R> extends Function<T,R> {
#Override
public default R apply(T t) {
try {
return throwingApply(t);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static<T,R> Function<T,R> wrap(ThrowingFunction<T,R> f) {
return f;
}
R throwingApply(T t) throws Exception;
}
and then
Stream.of("/somefile", "/someotherfile", "/yetanotherfile")
.map(Paths::get)
.flatMap(ThrowingFunction.wrap(Files::lines))
.....
There are several libraries out there that went through the trouble of writing something like the above out for every functional interface.
You can use following code
Files.list(Paths.get("path"))
.filter(Files::isRegularFile)
.flatMap(s -> {
try {
return Files.lines(s);
} catch (IOException e) {
e.printStackTrace();
}
return null;
})
.forEach(System.out::println);
With cyclops-streams (a library we have created) you can write
SequenceM.of("/somepathtofile1","/somepathtofile2")
.flatMapFile(File::new)
.forEach(System.out::println);
Javadoc SequenceM extends java.util.stream.Stream (and also org.jooq.lambda.Seq) to add a lot of additional convenience methods.