It is not clear that if IOException is thrown on server side in the
marshalling/unmarshalling process, what exception will be thrown on the client
side.
In current implementation, if an IOException occured unmarshalling remote call
parameters on server side, client will throw a ServerException with
UnmarshalException as the cause. This behavior is understandable as
ServerException should be used to wrap any RemoteException (UnmarshalException
in this case) thrown on server side.
However, if an IOException occured on marshalling return values on server side,
no MarshalException is thrown. Instead, the client will throw UnmarshalException
with a WriteAbortedException as the cause. This is hard to understand because
MarshalException wrapped by ServerException is more suitable in this case,
according to the spec.
The following program shows the behavior of current implementation:
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
import java.io.*;
public class MarshalTest {
public static void main(String[] args) throws Exception {
Registry registry = LocateRegistry.createRegistry(2000);
MarshalExceptionImpl remoteObj = new MarshalExceptionImpl();
Naming.bind("//:2000/test", remoteObj);
MarshalExceptionRemote remote = (MarshalExceptionRemote) Naming.lookup("//:2000/test");
System.out.println("IOException will happen on server when serializing the return object");
try {
remote.getObject(new SerialFailObject(false, false), false, true);
} catch (RemoteException e) {
System.out.println(e);
}
System.out.println();
System.out.println("IOException will happen on server when deserializing parameters");
try {
remote.getObject(new SerialFailObject(true, false), false, false);
} catch (RemoteException e) {
System.out.println("Exception thrown at client side is:");
System.out.println(e);
}
}
}
class SerialFailObject implements Serializable {
boolean readFail;
boolean writeFail;
public SerialFailObject(boolean r, boolean w) {
readFail = r;
writeFail = w;
}
private void writeObject(java.io.ObjectOutputStream out)
throws IOException {
out.defaultWriteObject();
if (writeFail) {
throw new IOException("IOException in serialization");
}
}
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException {
in.defaultReadObject();
if (readFail) {
throw new IOException("IOException in deserialization");
}
}
}
interface MarshalExceptionRemote extends Remote {
public SerialFailObject getObject(SerialFailObject obj, boolean readFail, boolean writeFail)
throws RemoteException;
}
class MarshalExceptionImpl extends UnicastRemoteObject implements MarshalExceptionRemote {
public MarshalExceptionImpl() throws RemoteException {
}
public SerialFailObject getObject(SerialFailObject obj, boolean readFail, boolean writeFail) {
return new SerialFailObject(readFail, writeFail);
}
}
The output in build 1.4.1-beta-b09 is:
IOException will happen on server when serializing the return object
Exception thrown at client side:
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.io.WriteAbortedException: writing aborted; java.io.IOException: IOException in serialization
IOException will happen on server when deserializing parameters
Exception thrown at client side is:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.io.IOException: IOException in deserialization
###@###.### 2002-04-19
marshalling/unmarshalling process, what exception will be thrown on the client
side.
In current implementation, if an IOException occured unmarshalling remote call
parameters on server side, client will throw a ServerException with
UnmarshalException as the cause. This behavior is understandable as
ServerException should be used to wrap any RemoteException (UnmarshalException
in this case) thrown on server side.
However, if an IOException occured on marshalling return values on server side,
no MarshalException is thrown. Instead, the client will throw UnmarshalException
with a WriteAbortedException as the cause. This is hard to understand because
MarshalException wrapped by ServerException is more suitable in this case,
according to the spec.
The following program shows the behavior of current implementation:
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
import java.io.*;
public class MarshalTest {
public static void main(String[] args) throws Exception {
Registry registry = LocateRegistry.createRegistry(2000);
MarshalExceptionImpl remoteObj = new MarshalExceptionImpl();
Naming.bind("//:2000/test", remoteObj);
MarshalExceptionRemote remote = (MarshalExceptionRemote) Naming.lookup("//:2000/test");
System.out.println("IOException will happen on server when serializing the return object");
try {
remote.getObject(new SerialFailObject(false, false), false, true);
} catch (RemoteException e) {
System.out.println(e);
}
System.out.println();
System.out.println("IOException will happen on server when deserializing parameters");
try {
remote.getObject(new SerialFailObject(true, false), false, false);
} catch (RemoteException e) {
System.out.println("Exception thrown at client side is:");
System.out.println(e);
}
}
}
class SerialFailObject implements Serializable {
boolean readFail;
boolean writeFail;
public SerialFailObject(boolean r, boolean w) {
readFail = r;
writeFail = w;
}
private void writeObject(java.io.ObjectOutputStream out)
throws IOException {
out.defaultWriteObject();
if (writeFail) {
throw new IOException("IOException in serialization");
}
}
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException {
in.defaultReadObject();
if (readFail) {
throw new IOException("IOException in deserialization");
}
}
}
interface MarshalExceptionRemote extends Remote {
public SerialFailObject getObject(SerialFailObject obj, boolean readFail, boolean writeFail)
throws RemoteException;
}
class MarshalExceptionImpl extends UnicastRemoteObject implements MarshalExceptionRemote {
public MarshalExceptionImpl() throws RemoteException {
}
public SerialFailObject getObject(SerialFailObject obj, boolean readFail, boolean writeFail) {
return new SerialFailObject(readFail, writeFail);
}
}
The output in build 1.4.1-beta-b09 is:
IOException will happen on server when serializing the return object
Exception thrown at client side:
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.io.WriteAbortedException: writing aborted; java.io.IOException: IOException in serialization
IOException will happen on server when deserializing parameters
Exception thrown at client side is:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.io.IOException: IOException in deserialization
###@###.### 2002-04-19
- relates to
-
JDK-5092823 The javadoc UnmarshalException don't elaborate on semantics
- Open