Date Serialization in RPC

1,814 views
Skip to first unread message

leslie

unread,
Jun 2, 2010, 7:24:22 AM6/2/10
to Google Web Toolkit
I'm attempting to send Date information from the client to the server
in a different timezone using remote procedure calls. As others have
already have commented, I am experiencing the expected change in value
of the Date because of the difference in the timezone.

I have found a post which describes the process of making changes to
the Custom Serializer for Date.
http://groups.google.com/group/google-web-toolkit/browse_thread/thread/fd7b80de11507908/2874ac102f17db26?lnk=gst&q=date+serialize#2874ac102f17db26

Is this still the appropriate method by which Date information should
be saved and if I need to recompile all of the GWT classes ( I hope
not ) which jar files am I re creating?

I notice that the thread is over a year and a half old. I was
wondering if any new methods or strategies are available as of GWT 2.0

Any information about the process of saving Date information is
appreciated. Thanks.

Lothar Kimmeringer

unread,
Jun 2, 2010, 7:29:42 AM6/2/10
to google-we...@googlegroups.com
leslie schrieb:

> I'm attempting to send Date information from the client to the server
> in a different timezone using remote procedure calls. As others have
> already have commented, I am experiencing the expected change in value
> of the Date because of the difference in the timezone.

Using java.util.Date this comes without surprise, because
Date itself doesn't contain any timezone-information.

> Is this still the appropriate method by which Date information should
> be saved and if I need to recompile all of the GWT classes ( I hope
> not ) which jar files am I re creating?

Saved or serialized? IMHO:

Saved: UTC-times
Serialized: W3C-formatted string representation of the date


Regards, Lothar

mariyan nenchev

unread,
Jun 2, 2010, 7:44:55 AM6/2/10
to google-we...@googlegroups.com
Why don't you use GMT times every where and just use the user's locale to format them in his/her timezone, but internally use Timestamp, or date.getTime() // long in gmt

Paul Robinson

unread,
Jun 2, 2010, 7:56:40 AM6/2/10
to google-we...@googlegroups.com
I had a recent search through everything related to this, and I believe
you have up-to-date information. Instead of recompiling GWT, I tried
putting the custom field serializers in my project and putting that
ahead of GWT in the classpath, but I couldn't make it work this way. I
went back to recompiling GWT.

I think this use case is way too common for it not to be supported
natively by GWT.

It's gwt-user.jar that contains the custom field serializers. Don't
forget that if you do this, you may need to change the custom field
serializers for java.sql.Date and java.sql.Timestamp if your project can
also send those via RPC.

Paul

leslie

unread,
Jun 2, 2010, 8:11:40 AM6/2/10
to Google Web Toolkit
(I apologize if this appears twice. I thought it was submitted but it
appears to have been lost.)

Thanks so much Lothar for your response.

--Using java.util.Date this comes without surprise, because
--Date itself doesn't contain any timezone-information.

This is true.

--Saved or serialized? IMHO:
--Saved: UTC-times
--Serialized: W3C-formatted string representation of the date

It looks like you are suggesting that rather than send the Date to the
server, Dates should be converted to Strings to be serialized? For
example, suppose I have a simple object "Person" with two attributes,
one of which is a Date.

public class Person {
private String fullname;
private Date birthdate;
}

I need to save the object on the server so I send it over RPC

public interface MyRPC extends RemoteService {
public void savePerson( Person person );
}
public interface MyRPCAsyc {
public void savePerson( Person person, AsyncCallback<Void> callback);
}

How should I send the Date information as String, at what point should
it be converted? I'd rather not change my model attributes from Date
type to String.

Thanks again.

leslie

unread,
Jun 2, 2010, 8:15:14 AM6/2/10
to Google Web Toolkit
Thanks marlyan for your repsonse

-- Why don't you use GMT times every where

I'm not sure what you mean here. I'm using the DateBox for the
convenience of my end user on my GWT gui and it returns a Date to the
model. That Date is serialized with the model object to be sent to
the server.

leslie

unread,
Jun 2, 2010, 8:22:25 AM6/2/10
to Google Web Toolkit
Thanks very much Paul for your response, for sharing your experience
and confirming what I guess I suspected. I guess I'm going to go
ahead and obtain the src files for the gwt-user jar, swap out the Date
Custom Serialization class and recompile and recreate the jar.
Fortunately, right now I'm only sending java.util.Date via RPC but
thanks for the heads up about TimeStamp and java.sql.Date.

On Jun 2, 7:56 am, Paul Robinson <ukcue...@gmail.com> wrote:
> I had a recent search through everything related to this, and I believe
> you have up-to-date information. Instead of recompiling GWT, I tried
> putting the custom field serializers in my project and putting that
> ahead of GWT in the classpath, but I couldn't make it work this way. I
> went back to recompiling GWT.
>
> I think this use case is way too common for it not to be supported
> natively by GWT.
>
> It's gwt-user.jar that contains the custom field serializers. Don't
> forget that if you do this, you may need to change the custom field
> serializers for java.sql.Date and java.sql.Timestamp if your project can
> also send those via RPC.
>
> Paul
>
>
>
> leslie wrote:
> > I'm attempting to send Date information from the client to the server
> > in a different timezone using remote procedure calls.  As others have
> > already have commented, I am experiencing the expected change in value
> > of the Date because of the difference in the timezone.
>
> > I have found a post which describes the process of making changes to
> > the Custom Serializer for Date.
> >http://groups.google.com/group/google-web-toolkit/browse_thread/threa...

Lothar Kimmeringer

unread,
Jun 2, 2010, 9:30:56 AM6/2/10
to google-we...@googlegroups.com
Hi Leslie,

first of all (offtopic), try to conform to the quoting standards.
preceding '--'s are not.

leslie schrieb:


>
> --Saved or serialized? IMHO:
> --Saved: UTC-times
> --Serialized: W3C-formatted string representation of the date
>
> It looks like you are suggesting that rather than send the Date to the
> server, Dates should be converted to Strings to be serialized? For
> example, suppose I have a simple object "Person" with two attributes,
> one of which is a Date.
>
> public class Person {
> private String fullname;
> private Date birthdate;
> }

We were talking about dates where you need timezones. A birthday
is a quite bad example for that.

> How should I send the Date information as String, at what point should
> it be converted? I'd rather not change my model attributes from Date
> type to String.

Date is just an Object around a long-value representing the
milliseconds since Jan 1, 1970 00:00:00 UTC. So you can send
the UTC time to the server or you evaluate the HTTP-request-
headers of the request on the server side to find out what
timezone the browser resides in to convert it to UTC on
server-side.


Regards, Lothar

leslie

unread,
Jun 2, 2010, 10:53:26 AM6/2/10
to Google Web Toolkit
No luck here..

I tried making the changes found in the file in the link I offered
earlier. Running with the new code produces the following error when
I attempt to retrieve a list of objects each with a Date attribute.

com.google.gwt.dev.shell.HostedModeException: Something other than an
int was returned from JSNI method
'@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::readInt()':
JS double value 3.693265408E9 out of range for a int
at com.google.gwt.dev.shell.JsValueGlue.getIntRange(JsValueGlue.java:
256)
at com.google.gwt.dev.shell.JsValueGlue.get(JsValueGlue.java:144)
at
com.google.gwt.dev.shell.ModuleSpace.invokeNativeInt(ModuleSpace.java:
242)
at
com.google.gwt.dev.shell.JavaScriptHost.invokeNativeInt(JavaScriptHost.java:
75)
at
com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader.readInt(ClientSerializationStreamReader.java)
at
com.google.gwt.user.client.rpc.core.java.util.Date_CustomFieldSerializer.instantiate(Date_CustomFieldSerializer.java:
21)

I don't know how to resolve this. So this strategy probably won't
work for me.

Note that the new gwt-user.jar file, like the previous, does not get
uploaded to the server with the rest of the project. I didn't need to
before and I didn't do it now. I simply recompiled my project with
the new gwt-user.jar on the build path. And then I created a war file
from the war directory and uploaded that war file.

The changes to the Date_CustomFieldSerializer class are in the
instantiate and serialize methods..

public static Date instantiate(SerializationStreamReader streamReader)
throws SerializationException {
// return new Date(streamReader.readLong());
return new
Date(streamReader.readInt(),streamReader.readInt(),streamReader.readInt(),
streamReader.readInt(),streamReader.readInt());
}

public static void serialize(SerializationStreamWriter streamWriter,
Date instance) throws SerializationException {
// streamWriter.writeLong(instance.getTime());
streamWriter.writeInt(instance.getYear());
streamWriter.writeInt(instance.getMonth());
streamWriter.writeInt(instance.getDate());
streamWriter.writeInt(instance.getHours());
streamWriter.writeInt(instance.getMinutes());
}

leslie

unread,
Jun 2, 2010, 11:08:10 AM6/2/10
to Google Web Toolkit
Hi Lothar, Thanks again for your help,
>
> first of all (offtopic), try to conform to the quoting standards.
> preceding '--'s are not.

Ok. You're right. Sorry about that.

> We were talking about dates where you need timezones. A birthday
> is a quite bad example for that.

Yes I see your point. However, the birthday information is precisely
the kind of information I am attempting to record. That is, a month,
day, year value that is fixed and independent of timezone.

I am using a DateBox on the GWT gui. And when I select June 1, 2010
as I run the application on my local machine, I can see that June 1,
2010 is stored with the data and this is correct. But when I run the
application online and select June 1, 2010 I see that May 31, 2010 is
stored with the data and that is not what I want.

> Date is just an Object around a long-value representing the
> milliseconds since Jan 1, 1970 00:00:00 UTC. So you can send
> the UTC time to the server or you evaluate the HTTP-request-
> headers of the request on the server side to find out what
> timezone the browser resides in to convert it to UTC on
> server-side.

This is a very good suggestion and this may help me with the
situation. I'll work with this idea a bit. Thanks again.

Paul Robinson

unread,
Jun 2, 2010, 11:11:21 AM6/2/10
to google-we...@googlegroups.com
I misled you slightly....the date/date/timestamp custom field
serializers are also in gwt-servlet.jar

Paul

kozura

unread,
Jun 2, 2010, 11:44:17 AM6/2/10
to Google Web Toolkit
Or, if all you really want is the actual date entered by the user and
don't care about the time, you can simply send yyyy mm dd, either as a
separate object or parameters to an RPC, and avoid custom serializers,
interpreting Universal Date against timezones, or recompiling GWT.
Why make sh*t complicated??

leslie

unread,
Jun 2, 2010, 12:31:28 PM6/2/10
to Google Web Toolkit
I'm converting an existing java desktop application to the web by
using GWT. The model classes are already written and they contain a
number of Dates. The Person example was a trivial representation of a
larger model. What you're suggesting is more complicated than you
realize.

leslie

unread,
Jun 2, 2010, 12:32:23 PM6/2/10
to Google Web Toolkit
That was it. Recompiling the servlet jar file with the updated Date
Custom Serializer class worked.
Thanks very much.

dfreis

unread,
Apr 13, 2012, 2:49:50 AM4/13/12
to google-we...@googlegroups.com
The problem I still had was in web mode in combination with tomcat.
Since it is not easy to control the Classloader in tomcat the gwt-servlet.jar was always loaded prior to my jar named owhatever.jar.
I figured out that tomcats classloader order is alway alphabetic so that g*.jar is always loaded prior to o*.jar.
So the com.google.gwt.user.client.rpc.core.java.util.Date_CustomFieldSerializer class was always token from gwt-servlet.jar.
To Solve this one could either rename the jars to be loaded in the desired order which I did not like since this might be implementation dependent or
to include the code from gwt-servlet.jar except of the Date_CustomFieldSerializer class within my owhatever.jar which I finally did!

Joseph Lust

unread,
Apr 20, 2012, 5:33:16 PM4/20/12
to google-we...@googlegroups.com
Have you implemented the custom date serializer noted in this post? It worked for me when there was a timezone issue between clients and servers being in different regions.



Here is my implementation of that solution. Note that I don't bother passing any thing less than seconds. If you don't need seconds you can save some space there too over the wire by removing them.

package com.google.gwt.user.client.rpc.core.java.util;

import java.util.Date;

import com.google.gwt.user.client.rpc.CustomFieldSerializer;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializationStreamReader;
import com.google.gwt.user.client.rpc.SerializationStreamWriter;

public final class Date_CustomFieldSerializer extends CustomFieldSerializer<java.util.Date> {

    public static void deserialize(SerializationStreamReader streamReader, Date instance) {
        // No fields
    }

    @SuppressWarnings("deprecation")
public static Date instantiate(SerializationStreamReader streamReader) throws SerializationException {
        return new Date(
        streamReader.readInt(),
        streamReader.readInt(),
        streamReader.readInt(),
        streamReader.readInt(),
        streamReader.readInt(),
        streamReader.readInt());
    }

    @SuppressWarnings("deprecation")
public static void serialize(SerializationStreamWriter streamWriter, Date instance) throws SerializationException {
        streamWriter.writeInt(instance.getYear());
        streamWriter.writeInt(instance.getMonth());
        streamWriter.writeInt(instance.getDate());
        streamWriter.writeInt(instance.getHours());
        streamWriter.writeInt(instance.getMinutes());
        streamWriter.writeInt(instance.getSeconds());
    }

    public void deserializeInstance(SerializationStreamReader streamReader, Date instance)
            throws SerializationException {
        deserialize(streamReader, instance);
    }

    @Override
    public boolean hasCustomInstantiateInstance() {
        return true;
    }

    @Override
    public Date instantiateInstance(SerializationStreamReader streamReader) throws SerializationException {
        return instantiate(streamReader);
    }

    public void serializeInstance(SerializationStreamWriter streamWriter, Date instance) throws SerializationException {
        serialize(streamWriter, instance);
    }

}


Sincerely,
Joseph

Reply all
Reply to author
Forward
0 new messages