B
Bill Michaelson
I have a server which writes various objects to an ObjectOutputStream
over a TCP connection to the client in response to requests. In the
case of certain objects, the client throws StreamCorruptedException.
Various objects present no problem, but certain objects do. Problem
started with an instance of this class...
class MMState implements java.io.Serializable {
Vector clientRq = new Vector();
HashMap userMap = new HashMap();
HashMap muSessMap = new HashMap();
public String toString () {
return "MMState:"
+"\nuserMap:\n"+userMap
+"\nmuSessMap:\n"+muSessMap
+"\nclientRq:\n"+clientRq;
}
}
----------------
I can send it successfully if I do toString() first. But sending object
causes client to throw the exception. Variations are described in
comments embedded in server code fragment below.
Interestingly, If I run the client on a separate system (JVM build
1.3.1_04-b02), it works OK. It only fails on a system with JVM build
1.4.2-b28. It matters not which system the server runs on, or whether
it is on the same box as the client.
The client code fragment from the superclass which does the readObject
is pasted below, FWIW.
I speculated that perhaps a timing issue is causing the object to be
modified in another thread during the writeObject. But I've used
synchronized to eliminate this possibility, to no avail.
---------------------------------------------------------------------------
SERVER SIDE
public boolean processSpecificRequest (Object o, boolean endBatch) {
synchronized (mother.userMap) {
M.moanln(M.XACTION+M.IPC+M.TRACE+4,"Msg from
("+clientID+"): "+o);
Object stat = null;
if (o instanceof MMWatchGroup) {
MMWatchGroup wg = (MMWatchGroup)o;
if (userService == null) stat = "Not logged in.";
else {
MMUserService us = (MMUserService)userService; //
better be!
us.muWatchList.addElement(wg);
stat = "Watch for "+wg+" added";
}
} else if (o instanceof RTUAIntervalTrack) stat = qU(o,false);
else if (o instanceof RouteDescription) stat = qU(o,false);
else if (o instanceof MUTell) stat = qU(o,true);
else if (o instanceof String) {
String s = (String)o;
if (s.equals("sdump")) {
M.moanln(M.XACTION+M.IPC+M.INFO,"sdump request");
// !! various forms of Exception occur in receiver (client) w/ commented
cases,
// including EOF and StreamCorrupted (don't know why).
// Works ok with toString() as work-around.
//stat = mms;
//stat = mms.clientRq; // chokes it!!
//stat = mms.userMap; // coughs (EOF) 1st time, then OK
//stat = mms.muSessMap; // OK
stat = mms.toString(); // this is OK
} else if (s.equals("splat")) {
M.moanln(M.XACTION+M.IPC+M.INFO,"splat request");
stat = "Splat, Joe\n";
} else
stat = "Unrecognized MobileMon request: "+s;
} else
stat = "Unrecognized MobileMon request: "+o;
if (stat == null) {
stat = "RQ processor return null stat!";
M.moanln(M.XACTION+M.IPC+M.ERROR,stat.toString());
}
M.moanln(M.XACTION+M.IPC+M.TRACE,"MM
response:\n"+stat.toString());
try {
oos.writeObject(stat); oos.flush();
}
catch (IOException ioe) {
M.moanln(M.XACTION+M.ERROR,"Cough. write: "+ioe);
}
// !! handle endbatch intelligently, move response to
processing above
// !! provide response method in this class
// !! enqueue object which includes xaction object +
MCSession obj
}
return true;
}
---------------------------------------------------------------------
CLIENT SIDE FRAGMENT
public Object receive (int timeoutms) {
if (!connected) return null;
try {
cSock.setSoTimeout(timeoutms);
} catch (SocketException se) {
M.moanln("Failed to set client socket timeout: "+se);
return null;
}
Object reply = null;
try {
try {
reply = ois.readObject();
} catch (InterruptedIOException iioe) {
M.moanln(M.IPC+M.TRACE+5,"Socket timeout");
reply = null; // !!maybe should send special object for this
}
} catch (Exception e) {
M.moanln(M.IPC+M.ERROR,"Exception in read object: "+e);
return e;
}
//M.moanln(M.IPC+M.TRACE,"Reply: "+reply);
return reply;
}
over a TCP connection to the client in response to requests. In the
case of certain objects, the client throws StreamCorruptedException.
Various objects present no problem, but certain objects do. Problem
started with an instance of this class...
class MMState implements java.io.Serializable {
Vector clientRq = new Vector();
HashMap userMap = new HashMap();
HashMap muSessMap = new HashMap();
public String toString () {
return "MMState:"
+"\nuserMap:\n"+userMap
+"\nmuSessMap:\n"+muSessMap
+"\nclientRq:\n"+clientRq;
}
}
----------------
I can send it successfully if I do toString() first. But sending object
causes client to throw the exception. Variations are described in
comments embedded in server code fragment below.
Interestingly, If I run the client on a separate system (JVM build
1.3.1_04-b02), it works OK. It only fails on a system with JVM build
1.4.2-b28. It matters not which system the server runs on, or whether
it is on the same box as the client.
The client code fragment from the superclass which does the readObject
is pasted below, FWIW.
I speculated that perhaps a timing issue is causing the object to be
modified in another thread during the writeObject. But I've used
synchronized to eliminate this possibility, to no avail.
---------------------------------------------------------------------------
SERVER SIDE
public boolean processSpecificRequest (Object o, boolean endBatch) {
synchronized (mother.userMap) {
M.moanln(M.XACTION+M.IPC+M.TRACE+4,"Msg from
("+clientID+"): "+o);
Object stat = null;
if (o instanceof MMWatchGroup) {
MMWatchGroup wg = (MMWatchGroup)o;
if (userService == null) stat = "Not logged in.";
else {
MMUserService us = (MMUserService)userService; //
better be!
us.muWatchList.addElement(wg);
stat = "Watch for "+wg+" added";
}
} else if (o instanceof RTUAIntervalTrack) stat = qU(o,false);
else if (o instanceof RouteDescription) stat = qU(o,false);
else if (o instanceof MUTell) stat = qU(o,true);
else if (o instanceof String) {
String s = (String)o;
if (s.equals("sdump")) {
M.moanln(M.XACTION+M.IPC+M.INFO,"sdump request");
// !! various forms of Exception occur in receiver (client) w/ commented
cases,
// including EOF and StreamCorrupted (don't know why).
// Works ok with toString() as work-around.
//stat = mms;
//stat = mms.clientRq; // chokes it!!
//stat = mms.userMap; // coughs (EOF) 1st time, then OK
//stat = mms.muSessMap; // OK
stat = mms.toString(); // this is OK
} else if (s.equals("splat")) {
M.moanln(M.XACTION+M.IPC+M.INFO,"splat request");
stat = "Splat, Joe\n";
} else
stat = "Unrecognized MobileMon request: "+s;
} else
stat = "Unrecognized MobileMon request: "+o;
if (stat == null) {
stat = "RQ processor return null stat!";
M.moanln(M.XACTION+M.IPC+M.ERROR,stat.toString());
}
M.moanln(M.XACTION+M.IPC+M.TRACE,"MM
response:\n"+stat.toString());
try {
oos.writeObject(stat); oos.flush();
}
catch (IOException ioe) {
M.moanln(M.XACTION+M.ERROR,"Cough. write: "+ioe);
}
// !! handle endbatch intelligently, move response to
processing above
// !! provide response method in this class
// !! enqueue object which includes xaction object +
MCSession obj
}
return true;
}
---------------------------------------------------------------------
CLIENT SIDE FRAGMENT
public Object receive (int timeoutms) {
if (!connected) return null;
try {
cSock.setSoTimeout(timeoutms);
} catch (SocketException se) {
M.moanln("Failed to set client socket timeout: "+se);
return null;
}
Object reply = null;
try {
try {
reply = ois.readObject();
} catch (InterruptedIOException iioe) {
M.moanln(M.IPC+M.TRACE+5,"Socket timeout");
reply = null; // !!maybe should send special object for this
}
} catch (Exception e) {
M.moanln(M.IPC+M.ERROR,"Exception in read object: "+e);
return e;
}
//M.moanln(M.IPC+M.TRACE,"Reply: "+reply);
return reply;
}