gwtproject / gwt

GWT Open Source Project
http://www.gwtproject.org
1.52k stars 375 forks source link

Serialize final fields in GWT-RPC #1062

Closed dankurka closed 8 years ago

dankurka commented 9 years ago

Originally reported on Google Code with ID 1054

Found in GWT Release:
All

Detailed description:
The current implementation of GWT RPC does not serialize final fields which hinders
the ability to 
use explicitly immutable objects.  The only obstacle to solving this problem is the
server side 
deserialization code.  The reason is that  the act of changing the value of a final
field via 
reflection is not clearly specified and is likely to be a JVM implementation detail.
 For example, 
the JRE itself uses unsafe methods to actually achieve this.

The solutions range from simply trying the reflective path to see if it works to actually
doing 
some form of GWT stream to Java serialized stream conversion and then using Java 
deserialization logic to handle the rest.  

Workaround if you have one:

Links to the relevant GWT Developer Forum posts:

Reported by gwt.team.mmendez on 2007-05-17 15:00:05

dankurka commented 9 years ago

Reported by gwt.team.morrildl on 2007-06-06 16:43:02

dankurka commented 9 years ago

Reported by jgw+personal@google.com on 2008-04-09 19:47:48

dankurka commented 9 years ago
The original reason for not doing this was that Java 1.4 did not allow it.  The problematic
comment is: "If the 
underlying field is final, the method throws an IllegalAccessException."  See the documentation
for 
Field.set(Object,Object), for more details.  Pay special attention to

In Java 1.5, this is possible with caveats.  We need to make sure that the following
description does not 
negatively impact GWT RPC deserialization: "Setting a final field in this way is meaningful
only during 
deserialization or reconstruction of instances of classes with blank final fields,
before they are made available 
for access by other parts of a program. Use in any other context may have unpredictable
effects, including 
cases in which other parts of a program continue to use the original value of this
field.".  See http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/Field.html#set(java.lang.Object,%20java.lang.Obje
ct),for more details.

Reported by mmendez+personal@google.com on 2008-04-14 13:18:13

dankurka commented 9 years ago
Any update on this issue? Are there any plans to support serializing final fields in

gwt 1.5. If not, I would say at the very least, the gwt compiler for 1.4 and 1.5 
should complain about serializing final fields. Currently, it treats it as a 
transient which is wrong. We got burned by this a few times. 

Reported by fazal.asim on 2008-06-19 16:11:29

dankurka commented 9 years ago
I agree with fazal.asim, final != transient and there's not reason to bite people 
with it.

Can we agree to at least turn the warning back on for GWT 1.5 and reenable 
"gwt.suppressNonStaticFinalFieldWarnings"?

Reported by scottb+legacy@google.com on 2008-08-18 23:20:00

dankurka commented 9 years ago
Just committed r3538 which re-enables the final field warning and suppression thereof.

Reported by mmendez+personal@google.com on 2008-08-19 14:56:27

dankurka commented 9 years ago

Reported by scottb+legacy@google.com on 2008-08-19 19:55:43

dankurka commented 9 years ago
Whoops, the underlying request to serialize final fields is not implemented.

Reported by scottb+legacy@google.com on 2008-08-19 21:16:34

dankurka commented 9 years ago

Reported by scottb+legacy@google.com on 2008-08-19 21:16:57

dankurka commented 9 years ago

Reported by bruce+personal@google.com on 2008-10-21 21:58:14

dankurka commented 9 years ago
Do you have an ETA for this getting fixed?

The implications trickle through tons of serializable classes, so the sooner you fix
it the easier it will be for the rest of us to adjust...

Reported by fry+legacy@google.com on 2009-02-17 21:01:16

dankurka commented 9 years ago
I believe that Lex owns this issue now.

Reported by mmendez+personal@google.com on 2009-02-17 21:04:50

dankurka commented 9 years ago
I would think that now is a good time to make this change, in trunk, since 1.6 is on
its way out the door.  That 
would give a lot of time to deal with repercussions before the next release.  Does
anyone see a reason not to 
switch over to allowing serializing final fields for GWT RPC?

There will be effects.  For people running on JVMs >= 1.5, the effect will be that
more classes and data are 
serialized and sent across the wire.  In cases where this is not desired, the previous
behavior can be gotten by 
marking final fields "transient".  This issue can be detected by looking at rpc.log
files before and after the 
relevant gwt update.

For people running on 1.4 JVMs, there might additionally be some deserialization exceptions.
 This effect could 
be minimized, though, if GWT's server-side support simply ignores such exceptions for
final fields.  As with the 
current system, such fields would be left in their default state.

I can't give an ETA, but I see your point and will put this on a shorter list.

Reported by spoon+personal@google.com on 2009-02-17 22:21:55

dankurka commented 9 years ago
Without being the wise guy, I think there is a workaround after all.

If Google's team makes GWT [de]serializators to make use of copy constructors, that
would both:

1. Not force GWT's implementation to stray from standard Java (which generally
rejects serializing final fields);

2. Respect the programming patterns on immutable objects -- never hack them being
mutable in _ANY_ way, rather provide means to easily copy them when necessary.

Plus, since many people will argue that this could break already existing code, I
will modify my suggestion a bit: better provide matchers for classes (or packages)
in
the GWT XML module definition where you can override this serialization issue.
Something like:

<module ...>
...

  <serialization-policy>

    <final-fields match-for="com.yourcompany.project.beans.*"
                  policy="use-copy-constructor"/>

    <final-fields match-for="com.yourcompany.project.external.beans.*"
                  policy="use-copy-method"
                  copy-method-name="deepCopy"/>

    <final-fields match-for="com.yourcompany.project.mock.*"
                  policy="use-static-factory-method"
                  static-factory-class-name="MockFactory"/>
                  static-factory-method-name="createAnonymousMock"/>

  </serialization-policy>

</module>

I would love any thoughts on these ideas.

Reported by mitko.p on 2009-02-18 11:23:14

dankurka commented 9 years ago
Actually, Java serialization does serialize final fields, with the exception of Java
1.4 VMs.  Here is the Sun bug 
report discussing the change to allow such serialization:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5044412

As discussed, immutable objects deserve to be serialized, too, in which case you either
need a way to modify 
final fields during deserialization, or you require objects with final fields to be
written in a more constrained 
style than is otherwise necessary.

So, while there are many ways to do RPC, allowing serialization of final fields sure
looks like a small and 
positive change to the existing system.

For the compatibility issue, I'm not sure what to do.  It seems like a simple and usable
starting point, though, 
to simply not set the fields when on Java 1.4.  That would preserve the GWT <= 1.6
behavior.

Reported by spoon+personal@google.com on 2009-02-18 22:04:11

dankurka commented 9 years ago
This is such a fundamentally important issue for my team. We always use the final
modifier on fields which don't change - and we enforce this with an IDE configured
to
warn when fields can be made final.

Our GWT code is littered with annotations to supress this, and comments to explain
why adding final will break the code.

    /**
     * NOTE: Don't make this final, as GWT serialization can not handle it.
     */
    @SuppressWarnings( {"FieldMayBeFinal"} )
    /*final */ private MyDate _date;

Reported by troy.jezewski on 2009-04-18 02:38:57

dankurka commented 9 years ago

Reported by scottb@google.com on 2010-02-03 17:02:34

dankurka commented 9 years ago
Any chance this goes into the experimental DeRPC (Direct Eval RPC)?

Reported by kaspar.fischer%dreizak.com@gtempaccount.com on 2010-06-10 21:41:46

dankurka commented 9 years ago
I'd also really really like this for at least DeRPC. Immutable objects are much easier
to reason about. This change has been in planning for nearly a year and a half - can
we at least get an idea of when it will appear in trunk? 

Reported by AtomicForce on 2010-06-14 01:08:28

dankurka commented 9 years ago

Reported by scottb@google.com on 2010-06-14 19:14:15

dankurka commented 9 years ago
Me

Reported by georg25ann on 2010-10-04 02:07:44

dankurka commented 9 years ago
deRPC already supports final field serialization.  Is the request to retrofit this into
the original RPC?

Reported by mmendez@google.com on 2010-10-28 14:19:49

dankurka commented 9 years ago

Reported by mmendez@google.com on 2010-10-28 14:21:05

dankurka commented 9 years ago
Are there any concrete plans on when this will be a part of the original RPC? It was
accepted almost two and a half years ago but it is unclear on which milestone it will
be released.

Reported by ittaiz on 2010-12-27 09:56:53

dankurka commented 9 years ago

Reported by rjrjr@google.com on 2011-01-13 03:12:14

dankurka commented 9 years ago

Reported by rjrjr@google.com on 2011-03-23 17:31:27

dankurka commented 9 years ago

Reported by rjrjr@google.com on 2011-03-25 21:34:55

dankurka commented 9 years ago

Reported by rjrjr@google.com on 2011-10-04 16:58:05

dankurka commented 9 years ago
@RayC, if you won't be able to review this please say so.

Reported by rjrjr@google.com on 2011-10-04 16:58:52

dankurka commented 9 years ago

Reported by rjrjr@google.com on 2011-10-04 16:59:06

dankurka commented 9 years ago
Issue 2156 has been merged into this issue.

Reported by stephen.haberman on 2011-10-10 20:44:39

dankurka commented 9 years ago
Issue 2244 has been merged into this issue.

Reported by stephen.haberman on 2011-10-10 21:07:45

dankurka commented 9 years ago
Issue 4931 has been merged into this issue.

Reported by stephen.haberman on 2011-12-26 18:02:50

dankurka commented 9 years ago
Would it be possible to use an annotation @SerializeFinalFields to tell the generator
to create _CustomFieldSerializer classes for any classes marked with the annotation,
which would manually serialize all final fields whenever a class has this annotation?
 I'm not sure how to properly generate the .setAccessible(true) for the server, or
if this is possible, but I do think a generator annotation which will not change any
existing code that may depend on the final fields being skipped would be optimal.

I'm also not sure about how to set final fields in the client, but one idea would be
to force users to also define and annotate a constructor which can be used to initialize
these fields during serialization.  Such a method would also avoid any overhead from
calling .setAccesible on the server.

The only problem I see here is if a _CustomFieldSerializer is already specified for
the class; though anyone using a custom serializer can serialize all the final and
transient fields they want...

Since I don't have access to the review rjrjr mentioned, I will offer to write a patch
for review; though I suspect Ray Cromwell would write a better implementation =}

Reported by James@wetheinter.net on 2012-01-17 23:32:11

dankurka commented 9 years ago
James, here is the review:

http://gwt-code-reviews.appspot.com/1380807/

Reported by stephen.haberman on 2012-01-18 04:20:46

dankurka commented 9 years ago
It's been several months since the last update to this important issue.  When might
I hope to see released?

Reported by cliffwd on 2012-04-07 00:07:16

dankurka commented 9 years ago
This bug hit Jigsaw when Eclipse automatically added "final" to some fields. Our general
reaction is that GWT-RPC should be avoided; I suspect that others will have similar
reactions when they get bitten by this.

Reported by sudit@google.com on 2012-06-26 20:51:15

dankurka commented 9 years ago
You are correct about Eclipse auto-adding. On the other hand. GWT-RPC Serialization
!= Java Serialization, something you must realize when reading the documentation. Second,
an IDE should not be leading in your choise of technology, Eclipse is just the tool.
I do agree that final fields just should be serialized tough and I am waiting eagerly
for this issue to be solved. We chose to use custom field serializers but to be honest
it's a pain and not so good for performance in bad browsers. But avoiding GWT-RPC because
of this? What would be your alternative?

Reported by sebastiaan.blommers on 2012-06-27 08:35:09

dankurka commented 9 years ago
Our alternative is JAX-RS (Jackson + Jersey) with RequestBuilder (GWT) and it has made
many things much cleaner and less error prone. Bonus of REST is that we can also use
other client technologies instead of GWT. It also works perfectly in OSGi environment
with no more classloading issues.

Reported by m.zdila on 2012-06-27 08:51:08

dankurka commented 9 years ago
GWT-RPC has some big outstanding issues that have not been fixed after years. They started
on DeRPC and that one got abandonned as well. If you need to send more than strings
or very simple objects then you should avoid GWT-RPC.

Reported by david.nouls on 2012-06-27 11:35:04

dankurka commented 9 years ago
> When might I hope to see released?

I'm working on addressing the GWT team's feedback on the patch. It won't make 2.5,
but probably 2.5.1.

Reported by stephen.haberman on 2012-06-27 16:15:26

dankurka commented 9 years ago
awesome!

Reported by sebastiaan.blommers on 2012-06-27 21:26:37

dankurka commented 9 years ago
Is this issue still going to make a chance for 2.5.1?

Reported by sebastiaan.blommers on 2012-12-03 12:40:47

dankurka commented 9 years ago

Reported by kurka.daniel on 2013-01-11 21:53:53

dankurka commented 9 years ago
This is a very old bug. On the other hand, we've lived with it this long, and it seems
risky to put into 2.5.1 at the last minute. Perhaps we should land it just after the
release?

Reported by skybrian@google.com on 2013-01-23 01:30:48

dankurka commented 9 years ago

Reported by kurka.daniel on 2013-03-12 12:11:45

dankurka commented 9 years ago
I redid the patch for 2.5.1+ (incl. trunk) after stepping through the latest of http://gwt-code-reviews.appspot.com/1380807/

It seems to work for me after adding the flag <set-property name="rpc.final.serialize"
value="false" />

I also added legacy:
+  /** 
+   * Legacy construct (ex. restlet gwt) by sblommers
+  */
+  public SerializableTypeOracleBuilder(TreeLogger logger, PropertyOracle propertyOracle,
GeneratorContext context) throws UnableToCompleteException {
+   this(logger, context);
+  }

To make sure restlet-gwt (current version) still works

Regards,
Sebastiaan

Reported by sebastiaan.blommers on 2013-03-25 20:48:06


dankurka commented 9 years ago
<set-property name="rpc.final.serialize" value="true" /> ofc :D

Reported by sebastiaan.blommers on 2013-03-25 21:01:02

dankurka commented 9 years ago
Can you please provide an update on this?

Reported by fry@google.com on 2013-06-03 13:11:18

dankurka commented 9 years ago
Hello there,

I cannot provide updates on this issue because I am no longer using GWT for
my project. I moved to vaading because it was virtually impossible to
serialize all the domains on my application and mimic them in javascript.

kind regards and best of luck
Carlos

Reported by carlos.mfa.martins on 2013-06-03 13:35:55