I'm having trouble finding a clean way to handle checked exceptions thrown by a lambda function passed as a parameter in Java.
I'm writing a Client which will interact via RMI with a Server to play a game; a Client needs to be registered on the Server to be able to login, and it needs to be logged in to play a game. It's a college project, so I have some constraint on what technologies I can use and what I need to do. In particular, when a method raises a RemoteException
I've been asked to retry to call the same method a few times. I'm using Java 8 and I wanted to experiment a little bit with lambdas.
The class I'm focusing on right now will be the interface the client will use to communicate with the server; as of now I have the following structure.
Note: most of the methods I need to implement are still to be written; I'm using a custom exception to remember to implement them.
ServerRMI.java
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface ServerRMI extends Remote {
public static final String name = "hangman_server_rmi_name";
public int login(String nick, String password)
throws WrongPasswordException,
RemoteException;
public void logout(String nick, int cookie)
throws UserNotLoggedException,
RemoteException;
public void register(String nick, String password)
throws UserAlreadyRegisteredException,
RemoteException;
}
ServerInterface.java
import java.net.InetAddress;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class ServerInterface {
private String nickname;
private InetAddress address;
private int port;
private ServerRMI serverRMI;
public ServerInterface(String nickname, InetAddress address, int port)
throws RemoteException, NotBoundException{
this.nickname = nickname;
this.address = address;
this.port = port;
this.serverRMI = getServerRMI(address, port);
}
private interface ConnectionAction<R,E extends Throwable> {
public R action() throws E;
}
private static <E extends Throwable,R> R tryManyTimes(int times, ConnectionAction<R,E> action)
throws E {
if (times <= 0) {
throw new IllegalArgumentException("Expected times > 0");
}
E lastException = null;
boolean done = false;
while (times > 0 && !done) {
try {
return action.action();
} catch (Exception e) {
times--;
lastException = (E) e;
}
}
throw lastException;
}
private static ServerRMI getServerRMI(InetAddress parAddress, int parPort)
throws RemoteException, NotBoundException {
final InetAddress address = parAddress;
final int port = parPort;
try {
final Registry registry = (Registry) tryManyTimes(3,
() -> //\
LocateRegistry.getRegistry(address.getHostAddress(), port));
return (ServerRMI) tryManyTimes(3, () -> registry.lookup(ServerRMI.name));
} catch (Exception e) {
if (e instanceof RemoteException) {
throw (RemoteException) e;
} else if (e instanceof NotBoundException) {
throw (NotBoundException) e;
} else {
throw new RuntimeException("Unexpected exception");
}
}
}
public void register(String password)
throws UserAlreadyRegisteredException,
ConnectionFailureException {
throw new NotImplementedException();
}
public void login(String password)
throws WrongPasswordException,
ConnectionFailureException {
throw new NotImplementedException();
}
public void logout()
throws IllegalStateException,
ConnectionFailureException {
throw new NotImplementedException();
}
public Game openGame(int players)
throws IllegalStateException,
GameAlreadyExistsException,
ConnectionFailureException {
throw new NotImplementedException();
}
public Game joinGame(String name)
throws IllegalStateException,
GameNotFoundException,
ConnectionFailureException {
throw new NotImplementedException();
}
Game.java
public class Game {
}
I'm not including the files with the custom exceptions I've defined; every custom exception, right now, extends RuntimeException
.
Is there some way to organize the code that lets me avoid the instanceof
uses in the body of getServerRMI
? Ideally, I would like to do something like:
catch (RemoteException | NotBoundException e) {
throw e;
}
Any suggestion on any other part of the code will be appreciated.
} catch (Exception e) {....}
as well. \$\endgroup\$ – rolfl Jun 18 '15 at 14:51catch (Exception e)
block; it works perfectly. If anyone wants to write an answer I'll accept it, otherwise I'll write one later. \$\endgroup\$ – gcali Jun 18 '15 at 15:06