GregorianCalendar applet and StreamCorruptedException

N

Nigel Wade

I've got rather a peculiar error with my applet client/server comms. The
applet opens a Socket and attempts to read some objects sent back by the
server. However, the applet throws a StreamCorruptedException.

I've managed to narrow the problem down to the GregorianCalendar class. If I
send a GregorianCalendar object, the *next* object I try to read will throw
the exception.

Now for the really intersting bit. If I set a policy of

grant {
permission java.security.AllPermission;
}

it works perfectly.


Does anyone have any idea why de-serializing a GregorianCalendar in an
applet might cause this problem?



The version of Java I'm using is 1.4.1.
 
R

Roedy Green

Does anyone have any idea why de-serializing a GregorianCalendar in an
applet might cause this problem?

That is puzzling. However, presumably you know the exact line it is
being thrown. You can look at the corresponding source in src.zip
which should give a glue.

Perhaps it has to do with reading some timezone descriptor file.
 
N

Nigel Wade

Roedy said:
That is puzzling. However, presumably you know the exact line it is
being thrown. You can look at the corresponding source in src.zip
which should give a glue.

That's a good suggestion. I'm currently finding the source for 1.4.1. When I
have it I'll look at the line in question. It does seem to be consistent and
completely repeatable.

I'm also downloading 1.4.2 to see if that has the same problem. I can't find
anything related to this issue in the bug database.
Perhaps it has to do with reading some timezone descriptor file

I thought something along those lines myself. But it's peculiar that it
fails with the StreamCorruptedException reading the next object rather than
some security exception while reading the GregorianCalendar.
 
J

John C. Bollinger

Nigel said:
That's a good suggestion. I'm currently finding the source for 1.4.1.
When I have it I'll look at the line in question. It does seem to be
consistent and completely repeatable.

I'm also downloading 1.4.2 to see if that has the same problem. I can't
find anything related to this issue in the bug database.


I thought something along those lines myself. But it's peculiar that it
fails with the StreamCorruptedException reading the next object rather
than some security exception while reading the GregorianCalendar.

For what it's worth, the Java Bug Parade contains more than one bug
related to serialization and deserialization of GregorianCalendars over
the years, some of them fairly recent. Most of the bugs are marked as
fixed, but that is always tied to a particular (sometimes still future)
release containing the fix. I have no clue whether this is of any help.


John Bollinger
(e-mail address removed)
 
N

Nigel Wade

John said:
For what it's worth, the Java Bug Parade contains more than one bug
related to serialization and deserialization of GregorianCalendars over
the years, some of them fairly recent. Most of the bugs are marked as
fixed, but that is always tied to a particular (sometimes still future)
release containing the fix. I have no clue whether this is of any help.


John Bollinger
(e-mail address removed)

Thanks for that.

I'd searched for GregorianCalendar and got over 300 hits, so narrowed it
down with StreamCorruptedException and got zero hits, so assumed it wasn't
there. Another search with GregorianCalendar and serialization throws up bug
4802409, which looks very similar.

This bug claims it's fixed in 1.4.1_03, but I've just tested 1.4.2_02 and
it's not fixed in that. And a related bug 4844924 claims that's not fixed
even in 1.5.beta1.

I'm going to follow those bug details and see if they isolate the problem I
have.
 
P

P.Hill

Nigel said:
I've managed to narrow the problem down to the GregorianCalendar class.
If I send a GregorianCalendar object, the *next* object I try to read
will throw the exception.

The easiest way to fix this problem is: If it hurts, don't do it! :)

What I mean by that is that I would recommend using the "token"/"Ticket"
pattern, if I have the name right. That is the pattern which when you
have a big object and you don't really want to hand around these
big objects, define an object which identifies the main object, not
just a value object, but something smaller, just the identity of the main
object. For example, not an employee, but his employee ID; not a
Driver, but his Driver License ID #.

The Calendar object in some cases may be easy to use, but it ain't
a small object. It has more code then you'd ever expect in it (which
doesn't effect serialization), al this code leads to more internal data
than you might suspect. It has multiple arrays of field values in it. It
has various timezone objects in it, the timezone class has huge lists
of timezone information in memory of all the known timezones. The list
goes on.

What to use instead? What is a token for what most people mean when
they are carrying around a Calendar? The existing Date object!
THE DATE OBJECT IS NOT DEPRECATED, only all the various lame
methods that claimed to help calculate dates are deprecated.
Date is left to HOLD a binary date. That is exactly what you
need here!

Serialize your containing object with a Date object, but not
the Calendar, when you need the calendar again get one
in the VM in which you are de-serializing. Usually this is just
the default one. You'll save ____lots____ of overhead.

Now you might need to send more, if your times are timezone aware
(you need to know the time is in the morning in Los Angles,
not sometime in the afternoon GMT, or whatever the TZ of your server
happend to be), then you can invent your own object, or you could
serialize a String containing a formatted date string including all the
fields you need (including TZ). Also please, if you do this use something
related to the standard ISO-8601 format YYYY-DD-MM HH:mm:ss.mmm
(with or without punctuation).

I really hate to see people thinking they need to push around
a Calendar which is more of a strategy pattern than some fancy
Date object during serialization when the few bytes of Date
object or a String Object works in nearly all cases.

I hope that helps,
-Paul
 
S

Sudsy

I really hate to see people thinking they need to push around
a Calendar which is more of a strategy pattern than some fancy
Date object during serialization when the few bytes of Date
object or a String Object works in nearly all cases.

I hope that helps,
-Paul

A refreshing voice of reason! To reduce it even further, a date in
most systems is merely a long containing the number of milliseconds
since the epoch, UTC (nee GMT). Create a Long object like this:

Date someTime; // obtain from somewhere
Long when = new Long( someTime.getTime() );

Pass that object. Reconstruct (in the local time zone, no less!)
like this:

Long when; // read from ObjectInputStream
GregorianCalendar cal = new GregorianCalendar();
cal.setTimeInMillis( when.longValue() );

As Paul notes, there's no need to be sending huge objects around.
 
P

P.Hill

Sudsy said:
P.Hill wrote:
A refreshing voice of reason!

That's not usually what my co-workers call me, particularly on a Friday :)
But thanks.
To reduce it even further, a date in
most systems is merely a long containing the number of milliseconds
since the epoch, UTC (nee GMT).

If I recall, the only difference between a Date and a long is that
a Date has a transient calendar field (for formatting toString), otherwise
internally it is a long, so I would just lean toward stronger typing.
Create a Long object like this:

Date someTime; // obtain from somewhere

From a calendar oddly enough it's:

Date theDate = cal.getTime();

I blame that on 'prior art'.
Long when = new Long( someTime.getTime() );

Pass that object. Reconstruct (in the local time zone, no less!)
like this:

Long when; // read from ObjectInputStream
GregorianCalendar cal = new GregorianCalendar();
cal.setTimeInMillis( when.longValue() );

Date.getTime() will do the same thing.

Of course that leads to the most curious of chained calls

cal.getTime().getTime(); !!!
As Paul notes, there's no need to be sending huge objects around.

thank's for encouraging my point.

Oh yes, I was talking about the more basic class, java.util.Date. There
are other Dates running around in the JDK, most are subclasses of java.util.Date.

-Paul

p.s. What IS the right name for this pattern? Billet, Ticket, Token,
Ticky-Tacky, Postit-Note Pattern, ID Pattern?
 
N

Nigel Wade

P.Hill said:
The easiest way to fix this problem is: If it hurts, don't do it! :)

Already done.
What I mean by that is that I would recommend using the "token"/"Ticket"
pattern, if I have the name right. That is the pattern which when you
have a big object and you don't really want to hand around these
big objects, define an object which identifies the main object, not
just a value object, but something smaller, just the identity of the
main object. For example, not an employee, but his employee ID; not a
Driver, but his Driver License ID #.

Unfortunately that method isn't applicable here. The client *must* get the
full data record. What's required is to provide a suitable mechanism for the
date/time.

[snip]
I really hate to see people thinking they need to push around
a Calendar which is more of a strategy pattern than some fancy
Date object during serialization when the few bytes of Date
object or a String Object works in nearly all cases.

To be honest, I never intended to send a Calendar with the data. The
software is still in the early development stage and and the class defining
the data has methods to read it from the actual radar. This includes a
GregorianCalendar for converting from the radar's idea of time into a Java
Date. Rather than create a new Calendar each time a record is read I create
one in the constructor. Unfortunately, I didn't add the transient modifier...

But, when I found that I couldn't de-serialize the class I wanted to find
out why. And when I discovered that attempting to de-serialize a
GregorianCalendar in an applet caused an Exception I was even more curious
(even though I'd already cured the problem in the application).
 
P

P.Hill

Nigel said:
Already done.

Great, glad you eliminated the problem. Putting transient on the calendar
member of your containing object then doing lazy/late instantiation is
certainly the solution I would use.

Whenever I do lazy/late instantiation I do something like:

private Calendar getCalendar() {
if ( this.calendar == null ) {
...
}
return this.calendar;
}

What I mean by that is that I would recommend using the
"token"/"Ticket" pattern, if I have the name right.
[...]

Unfortunately that method isn't applicable here. The client *must* get
the full data record. What's required is to provide a suitable mechanism
for the date/time.

Just to clarify, I was not suggesting that you use this pattern on whatever
object contained the Date and Calendar, but to use it on the Calendar itself.
Capturing the state of or ID of a Calendar can often be done with a Date
object, in the similar way that capturing the 'state' or ID of an employee
object can sometimes be done by simply saving an appropriate employee ID.

-Paul
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top