Issue in wrapping input in Function interface - java

This question is related to Issue in abstracting common code using function interface and Exception handling in Function interface. Getting idea from those I have written like below:
public void act(Input1 input) throws NonRetriableException, InvalidInputException {
Function<UpdateTaskInput, Boolean> func = item -> {
try {
activityManager.update(item);
return true;
} catch (InterruptedException | JSONException e) {
throw new NonRetriableException(e);
} catch (LockUnavailableException e) {
throw new NonRetriableException(e);
}
};
try {
lockManager.executeWithLock(input.getTaskID(), input, func);
} catch (LockUnavailableException e) {
log.error("{}",e);
throw new NonRetriableException(e);
}
}
and:
public void perform()
throws AutoAllocationException {
Function<UpdateTaskInput, Boolean> func = item -> {
try {
activityManager.allocateTask(item);
return true;
} catch (AutoAllocationException ex) {
log.error("{}",ex);
}
return false;
};
try {
lockManager.executeWithLock(input.getTaskID(), input, func);
} catch (LockUnavailableException e) {
log.error("{}",e);
}
}
executeWithLock() in LockManager is as follows:
#Override
public <T,R> R executeWithLock(String lockName, T input, Function<T,R> func) throws LockUnavailableException {
LockItem lockItem = acquireLock(lockName);
try {
R output = func.apply(input);
return output;
} finally {
releaseLock(lockItem);
}
}
Now the issue with the executeWithLock() function is, it always expects input as an argument, I cannot invoke this for any other function which does not have any input like doStuff().
But I would like to do it using Function interface only with something like following ( so you can see, T is omitted).
#Override
public <R> R executeWithLock(String lockName, Function<R> func) throws LockUnavailableException {
LockItem lockItem = acquireLock(lockName);
try {
R output = func.apply(input);
return output;
} finally {
releaseLock(lockItem);
}
}
Is there any way to do that with Function interface?

You could use a intermediate helper method, which accepts a Supplier<R> but no input. Which then creates a Function<?, R> and delegates to the other method:
public <R> R executeWithLock(String lockName, Supplier<R> supplier) throws LockUnavailableException{
return executeWithLock(
lockName,
null, // input is ignored by our function
ignored -> supplier.get() // this lambda will create Function<?, R> from the Supplier<R>
);
}
This could then be used like this:
executeWithLock("mylock", () -> "Some Value");
Whereas () -> "Some Value" is a Supplier<String>.
If you can't change that code, and thus not be able to add a intermediate helper method. You might just want to pass null as an argument, and then ignore it in the lambda:
executeWithLock("myLock", null, ignored -> doStuff());

You need two methods. The first should take a Supplier rather than a Function and the input. Using Supplier is preferable because it gives you the flexibility to use zero or more input arguments. Using Function means you are limited to one.
You also need a second method which uses Runnable which supports zero or more input arguments and a void return:
public static <R> R executeWithLock(String lockName, Supplier<R> func) {
Lock lockItem = acquireLock(lockName);
try {
return func.get();
} finally {
releaseLock(lockItem);
}
}
public static void executeWithLock(String lockName, Runnable func) {
Lock lockItem = acquireLock(lockName);
try {
func.run();
} finally {
releaseLock(lockItem);
}
}
Sample usage for these example methods:
private static String foo(String input) { return input; }
private static void bar(String input) { }
would look like:
String ret = executeWithLock("lockName", () -> foo("someInput"));
executeWithLock("lockName", () -> bar("someInput")); // void return
Java is able to infer which version of executeWithLock is required based on whether or not there's a return type. If you wanted to be explicit, you could give the methods different names.

Related

Avoiding code duplication when checking for default responses

I have a Java program that calls an external API (RealApi in the code below) and sometimes I want to avoid calling this API and instead return pre-constructed responses (generated by FakeApi).
So, I ended up duplicating this kind of construct in most of my methods:
public Type1 m1(String s) {
try {
Type1 r = FakeApi.m1(s);
if (r != null) {
return r;
}
} catch (Exception e) {
// log error
}
return RealApi.m1(s);
}
What are some options to avoid duplicating this try/catch block everywhere? It's important that if FakeApi throws an exception or returns null, the RealApi must be called.
One option would be encapsulate the error checking behaviour into its own method:
public <T> T fakeOrReal(Supplier<T> fake, Supplier<T> real) {
try {
T r = fake.get();
if (r != null) {
return r;
}
}
catch (Exception e) {
// log error
}
return real.get();
}
You can then just call it with
public Type1 m1(String s) {
return fakeOrReal(() -> FakeApi.m1(s), () -> RealApi.m1(s));
}
This is not as simple as Thomas Preißler's answer but it will help you not repeat any method at all. So if you expand the interface, you have to modify only the concrete classes and not the linker which describes the actual behavior you want.
Create an interface that contains all the methods of RealApi:
interface Api {
Type1 m1(String s);
}
Then a class that does the actual call:
class ConcreteApi implements Api {
public Type1 m1(String s) {
return RealApi.m1(s);
}
}
Then create your FakeApi:
class TotallyFakeApi implements Api {
public Type1 m1(String s) {
return FakeApi.m1(s);
}
}
Now, the tricky part to avoid repeating yourself:
private static Object callImplementation(Api api, Method method, Object[] methodArgs) throws Exception {
Method actualMethod = api.getClass().getMethod(actualMethod.getName(), actualMethod.getParameterTypes());
return actualMethod.invoke(api, methodArgs);
}
Api fakeOrReal(Api fakeApi, Api realApi) {
return (Api) Proxy.newProxyInstance(
FakeApi.class.getClassLoader(),
new Class[]{Api.class},
(proxy, method, methodArgs) -> {
try {
Object r = callImplementation(fakeApi, method, methodArgs);
if (r != null) {
return r;
}
} catch (Exception e) {
// logError(e);
}
return callImplementation(realApi, method, methodArgs);
}
);
}
Get the actual implementation like this:
Api apiToUse = fakeOrReal(new TotallyFakeApi(), new ConcreteApi());

Java8: how to copy values of selected fields from one object to other using lambda expression

I'm trying to understand new functions of java8: forEach and lambda expressions.
Trying to rewrite this function:
public <T extends Object> T copyValues(Class<T> type, T source, T result)
throws IllegalAccessException
{
for(Field field : getListOfFields(type)){
field.set(result, field.get(source));
}
return result;
}
using lambda.
I think it should be something like this but can't make it right:
() -> {
return getListOfFields(type).forEach((Field field) -> {
field.set(result, field.get(source));
});
};
The loop can be replaced by
getListOfFields(type).forEach((field) -> field.set(result, field.get(source)));
However, that forEach method call has no return value, so you still need to
return result;
separately.
The full method:
public <T extends Object> T copyValues(Class<T> type, T source, T result)
throws IllegalAccessException
{
getListOfFields(type).forEach((field) -> field.set(result, field.get(source)));
return result;
}
EDIT, I didn't notice the issue with the exception. You'll have to catch the exception and throw some unchecked exception. For example:
public <T extends Object> T copyValues(Class<T> type, T source, T result)
{
getListOfFields(type).forEach (
(field) -> {
try {
field.set(result, field.get(source));
} catch (IllegalAccessException ex) {
throw new RuntimeException (ex);
}
});
return result;
}
You could use functions in the following way:
#FunctionalInterface
interface CopyFunction<T> {
T apply(T source, T result) throws Exception;
}
public static <T> CopyFunction<T> createCopyFunction(Class<T> type) {
return (source, result) -> {
for (Field field : getListOfFields(type)) {
field.set(result, field.get(source));
}
return result;
};
}
And then:
A a1 = new A(1, "one");
A a2 = new A(2, "two");
A result = createCopyFunction(A.class).apply(a1, a2);
The CopyFunction functional interface is pretty much the same as BinaryOperator except that BinaryOperator doesn't throw an exception. If you want to handle exceptions within a function, you can use the BinaryOperator instead.

Java 8 Stream. Throw exception to client method inside lambda expression

I've seen a few questions related to this, but I need a clear answer. I do understand the context where lambda expressions run, and the concept of side effects, but I believe there is a workaround I'm not seeing here.
I need to map a list of personas based on their sex, but the method I use to determine their sex returns a checked exception, which is not something the Collectors.groupingBy likes, at all.
Getting rid of the checked exception is not an option, and I need to send it up to the client method who invoked my piece of code. I there anything I can do around it?
public class Example {
public static void main(String[] args) {
Example example = new Example();
try {
example.runExample();
} catch (MException e) {
//Place where I want to handle the exception
}
}
private void runExample() throws MException{
List<Person> personas = Arrays.asList(new Person("Sergio", "234456789", 35), new Person("Mariana", "123456789", 38));
Map<String, List<Person>> personsBySex = personas.stream().collect(Collectors.groupingBy(persona -> {
try {
return getSex(persona.getSSN());
} catch (MException e) {
}
return null;
//Compiler forces me to return a value, but I don't want to return null.
//I want to throw up the MException to the client method (main)
}));
}
private String getSex(String ssn) throws MException {
// Imagine here is a call to an outside service that would give me the
// sex based on the SSN, but this service could return an exception as
// well
if (ssn.isEmpty())
throw new MException();
return ssn.startsWith("1") ? "Female" : "Male";
}
}
class Person {
private String name, ssn;
private Integer age;
public Person(String name, String ssn, Integer age) {
this.name = name;
this.ssn = ssn;
this.age = age;
}
public String getName() {return name;}
public String getSSN() {return ssn;}
public Integer getAge() {return age;}
}
class MException extends Exception {
}
Thanks for any ideas!
A workaround could be wrapping your checked exception with an unchecked one and throwing the latter from the catch block. Note that we are saving an MException as a cause to be able to work with further.
try {
return getSex(persona.getSSN());
} catch (MException e) {
throw new IllegalArgumentException(e); // choose a suitable runtime one
}
Another way to go (rather a modification of the previous one, I don't like that) would be writing a Collectors.groupingBy-friendly method to move the foregoing logic into:
private String getSexFriendly(String ssn) {
try {
return getSex(ssn);
} catch (MException e) {
throw new IllegalArgumentException(e);
}
}
Though, we will have a good-looking lambda:
persona -> getSexFriendly(persona.getSSN())
Forget about wrapping your exception - you can utilize the "sneaky throws' hack here which enables you to trick the compiler to think that your exception is not checked - this exploits the type inference rule introduced in Java 8.
Let's recreate your problem:
public Integer toInteger(String string) throws IOException {
throw new IOException("whoopsie!");
}
Stream.of("42")
.collect(Collectors.groupingBy(o -> toInteger(o))); // does not compile
Usually, you'd need to try-catch the exception just like you did, but there is a workaround:
#Test
public void example_1() throws Exception {
Stream.of("42")
.collect(Collectors.groupingBy(unchecked(this::toInteger)));
}
public Integer toInteger(String string) throws IOException {
throw new IOException("whoopsie!");
}
private static <T, R> Function<T, R> unchecked(ThrowingFunction<T, R> f) {
return t -> {
try {
return f.apply(t);
} catch (Throwable thr) {
return ThrowingFunction.sneakyThrow(thr);
}
};
}
public interface ThrowingFunction<T, R> {
R apply(T t) throws Throwable;
#SuppressWarnings("unchecked")
static <T extends Throwable, R> R sneakyThrow(Throwable t) throws T {
throw (T) t;
}
}
Firstly, you need to create your own functional interface for representing a function that can throw exceptions. In this case, ThrowingFunction.
Then, you can create a utility method that will repackage your checked lambda into a standard java.util.function. In this case, unchecked().
The last step is to create a method that sneakily throws an exception. In this case, sneakyThrow().
Actually, I think I will write an article about this.
EDIT:
I wrote: http://4comprehension.com/sneakily-throwing-exceptions-in-lambda-expressions-in-java/

Detect whether lambda is a method reference

Is there a way to determine whether a given Java lambda object is a method reference or a "CallSite-specific" lambda:
boolean isMethodReference(Object lambda)
Positive example:
assertTrue(isMethodReference(Object::toString));
Negative example with "CallSite-specific" lambda:
long valueFromCallSite = System.currentTimeMillis();
Consumer<Object> lambda = o -> {
if (valueFromCallSite % 2 == 0) {
o.toString();
} else {
o.hashCode();
}
};
assertFalse(isMethodReference(lambda));
A heuristic approach for isMethodReference(lambda) was proposed in "Determine if a lambda expression is stateless or stateful in Java":
boolean isMethodReference(Object lambda) {
return lambda.getClass().getDeclaredFields().length == 0;
}
It’s only a heuristic because it relies on unspecified behavior and thus is JDK implementation-specific and even might break in a future version.
It is possible to determine if a Java method reference is equivalent to another method reference. Assuming we have an interface User:
public interface User {
String firstName();
}
then we can do this:
public class Main {
public static void main(String[] args) {
print(User::firstName);
print(u -> u.firstName());
}
public interface SerializableFunction<T, R> extends Serializable, Function<T, R> {
}
private static void print(SerializableFunction<User, String> function) {
System.out.println("function = " + function);
if (Arrays.equals(serialize(function), serialize(User::firstName))) {
System.out.println("which is the method reference User::firstName");
}
}
private static byte[] serialize(SerializableFunction<User, String> function) {
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) {
objectOutputStream.writeObject(function);
return byteArrayOutputStream.toByteArray();
} catch (IOException e) {
return new byte[0];
}
}
}
This will print something like this:
function = software.chronicle.refactor.demo.serialization.Main$$Lambda$25/0x0000000800c02658#65ab7765
which is the method reference User::firstName
function = software.chronicle.refactor.demo.serialization.Main$$Lambda$33/0x0000000800c02b08#6659c656
So, it is actually possible to check if a lambda is a specific method reference.

Java 8: Chain Consumer<Y> to Function<X,Y>

Exploring the new features of Java 8, I stumbled the wish to create a Consumer<X> by chaining a Consumer<Y> to Function<X,Y>.
Does this make sense? And if so, how would a good (general) solution look like?
What I've tried (rather a special case by example):
Given
#FunctionalInterface
public interface PartialFunction<X, Y> {
Y apply(X x) throws Exception;
}
and
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
public class PartialFunctions {
public static <X, Y> Function<X, Optional<Y>> withOptionalResults(final PartialFunction<X, Y> funcThatThrows) {
return z -> {
try {
return Optional.of(funcThatThrows.apply(z));
} catch (final Exception e) {
return Optional.empty();
}
};
}
public static <X, Y> Consumer<X> acceptOnSuccess(final PartialFunction<X, Y> g, final Consumer<Y> c) {
return x -> withOptionalResults(x).apply(t).ifPresent(c);
}
}
I end up with a possible usage like:
files.forEach(PartialFunctions.<File, BufferedImage>acceptOnSuccess(
ImageIO::read, images::add));
However, the need for the explicit generic specification is not optimal.
Hopefully there is something better?
interface IgnoreThrowing<F,V> extends Function<F,V> {
public default V apply(F from) {
try {
return ignore(from);
} catch(Exception e) {
return null;
}
}
public V ignore(F from) throws Exception;
}
class Throwables {
public static <F,V> Function<F,V> ignore(IgnoreThrowing<F,V> f) {
return f;
}
}
static {
files.map(Throwables.ignore(ImageIO::read)).collect(...)
}
It will get better if you add a Collector that ignores nulls as input.
edit: i wrote this without syntax checking or compiling, so not totally sure about the placement of the default, and whether the compiler can successfully infer the chained function type parameters.
You could extend the Function interface like so:
public interface ComposableFunction<T, R> extends Function<T, R> {
default Consumer<T> andThen(Consumer<R> after) {
Objects.requireNonNull(after);
return (T t) -> {after.accept(apply(t));};
}
}
And then use it regularly like so:
ComposableFunction<Throwable, String> getMessage = Throwable::getMessage;
Consumer<String> log = System.out::println;
Consumer<Throwable> logMessage = getMessage.andThen(log);
You could try something like this?
public void lambdaChaining() {
System.out.println("\nlambda chaining:");
List<String> l = Arrays.asList("1", "22", "333", "4444", "55555", "666666", "7777777", "88888888", "999999999");
Function<String, ?> f = s -> s.length();
Consumer<String> c = s -> System.out.println(f.apply(s));;
l.forEach(c);
}
the other option (and the more general case) would be to use new Function<X,Y>(...).andThen(new Function<Y,Z>(...)). I wouldnt mix consumers and functions, rather chain functions then feed into consumers (who optionally are also chained).

Categories