When I am trying to send an object as an argument to rmi I am getting such an Exception:
HelloClient exception: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: IntegralClient$1 (no security manager: RMI class loader disabled)
Could you please help me to figure out what is wrong with my code and rmi server-client relationship implementation?
Here is my code:
ServerSide:
import java.rmi.*;
import java.rmi.server.*;
public class IntegralServer
{
public static void main (String[] argv)
{
try
{
IntegralComputeEngine integralCounter = new IntegralComputeEngine();
Naming.rebind("rmi://localhost/integral", integralCounter);
System.out.println("Integral Server is ready.");
}
catch (Exception e)
{
System.out.println("Addition Server failed: " + e);
}
}
}
Client side:
import java.rmi.*;
public class IntegralClient
{
public static void main(String[] args)
{
try
{
IntegralComputeEngineInterface integralCounter = (IntegralComputeEngineInterface) Naming.lookup("rmi://localhost/integral");
double result = integralCounter.computeIntegral(createFunction(), -1, 1);
System.out.println("Result is: " + result);
}
catch (Exception e)
{
System.out.println("HelloClient exception: " + e);
}
}
private static Function createFunction()
{
return new Function()
{
@Override
public double valueIn(double x)
{
return 1-x;
}
};
}
}
Function interface (which resides in both client and server projects):
import java.io.Serializable;
public interface Function extends Serializable
{
public double valueIn(double x);
}
IntegralComputeEngineInterface (which resides in both client and server projects):
import java.rmi.*;
public interface IntegralComputeEngineInterface extends Remote
{
public double computeIntegral(Function function, double from, double to) throws RemoteException;
}
IntegralComputeEngineInterface (which resides only on server):
import java.rmi.*;
import java.rmi.server.*;
public class IntegralComputeEngine extends UnicastRemoteObject implements IntegralComputeEngineInterface
{
private final double ACCURACY = 100;
protected IntegralComputeEngine() throws RemoteException
{super();}
@Override
public double computeIntegral(Function function, double from, double to) throws RemoteException
{
double stepValue = (to - from) / ACCURACY;
double stepLength = Math.abs(stepValue);
double result = 0.0;
for(int i = 0; i < ACCURACY; i++)
{result += stepLength * function.valueIn(from + stepValue*(i + 0.5));}
return result;
}
}
Here is screenshot of my project organization:
Will appreciate any help with regard to my problem!
I found this: An argument to, or a return value from, a remote object can be any object that is serializable. This includes primitive types, remote objects, and non-remote objects that implement the java.io.Serializable interface. For more details on how to make classes serializable, see the "Java Object Serialization Specification." Classes, for parameters or return values, that are not available locally are downloaded dynamically by the RMI system. See the section on "Dynamic Class Loading" for more information on how RMI downloads parameter and return value classes when reading parameters, return values and exceptions. Here.
According to this there must be no problems in my passing of the arguments, but still they are.
You should create a new class, extend UnicastRemoteObject and implement your Function simultaneously and it will be able to send such object over rmi arguments without any problems.
So, I changed your Function to FunctionInterface, created new class Function:
import java.rmi.RemoteException;
import java.rmi.server.*;
public class Function extends UnicastRemoteObject implements FunctionInterface
{
protected Function() throws RemoteException
{super();}
@Override
public double valueIn(double x)
{
return 1-x;
}
}
So my IntegralClient looks now so:
import java.rmi.*;
public class IntegralClient
{
public static void main(String[] args)
{
try
{
IntegralComputeEngineInterface integralCounter = (IntegralComputeEngineInterface) Naming.lookup("rmi://localhost/integral");
double result = integralCounter.computeIntegral(createFunction(), -1, 1);
System.out.println("Result is: " + result);
}
catch (Exception e)
{
System.out.println("HelloClient exception: " + e);
}
}
private static Function createFunction() throws RemoteException
{
// return new FunctionInterface()
// {
// @Override
// public double valueIn(double x)
// {
// return 1-x;
// }
// };
return new Function();
}
}
And it works!