Well, in the light of the "don't use GWTRPC because it won't be supported 
in the future", I'd say to you to just use REST and forget about this stuff.

"Easy to say" - I know.

One thing that I did to avoid all the serialization problems with GWT was 
to create my own SerializationPolicy, allowing everything which is instance 
of Serializable to be... well... serializable.

I use this "hack" since GWT 2.5 I think.

Here is the code:

public class CustomSerializationPolicy extends SerializationPolicy 
implements TypeNameObfuscator {

    private static final String ELISION_ERROR = "Type name elision in RPC "
            + "payloads is only supported if the RPC whitelist file is 
used.";

    /**
     * Many JRE types would appear to be {@link Serializable} on the server.
     * However, clients would not see these types as being {@link 
Serializable}
     * due to mismatches between the GWT JRE emulation and the real JRE. As 
a
     * workaround, this blacklist specifies a list of problematic types 
which
     * should be seen as not implementing {@link Serializable} for the 
purpose
     * matching the client's expectations. Note that a type on this list 
may still
     * be serializable via a custom serializer.
     */
    private static final Class<?>[] JRE_BLACKLIST = {
        java.lang.ArrayStoreException.class, java.lang.AssertionError.class,
        java.lang.Boolean.class, java.lang.Byte.class, java.lang.Character.
class,
        java.lang.Class.class, java.lang.ClassCastException.class,
        java.lang.Double.class, java.lang.Error.class, java.lang.Float.class
,
        java.lang.IllegalArgumentException.class,
        java.lang.IllegalStateException.class,
        java.lang.IndexOutOfBoundsException.class, java.lang.Integer.class,
        java.lang.Long.class, java.lang.NegativeArraySizeException.class,
        java.lang.NullPointerException.class, java.lang.Number.class,
        java.lang.NumberFormatException.class, java.lang.Short.class,
        java.lang.StackTraceElement.class, java.lang.String.class,
        java.lang.StringBuffer.class,
        java.lang.StringIndexOutOfBoundsException.class,
        java.lang.UnsupportedOperationException.class, java.util.ArrayList.
class,
        java.util.ConcurrentModificationException.class, java.util.Date.
class,
        java.util.EmptyStackException.class, java.util.EventObject.class,
        java.util.HashMap.class, java.util.HashSet.class,
        java.util.MissingResourceException.class,
        java.util.NoSuchElementException.class, java.util.Stack.class,
        java.util.TooManyListenersException.class, java.util.Vector.class};

    private static final Set<Class<?>> JRE_BLACKSET = new HashSet<Class<?>>(
            Arrays.asList(JRE_BLACKLIST));

    private static final CustomSerializationPolicy sInstance = new 
CustomSerializationPolicy();

    public static CustomSerializationPolicy getInstance() {
        return sInstance;
    }

    /**
     * Singleton.
     */
    private CustomSerializationPolicy() {
    }

    /**
     * Implemented to fail with a useful error message.
     */
    public final String getClassNameForTypeId(String id)
            throws SerializationException {
        throw new SerializationException(ELISION_ERROR);
    }

    /**
     * Implemented to fail with a useful error message.
     */
    public final String getTypeIdForClass(Class<?> clazz)
            throws SerializationException {
        throw new SerializationException(ELISION_ERROR);
    }

    @Override
    public boolean shouldDeserializeFields(Class<?> clazz) {
        return isFieldSerializable(clazz);
    }

    @Override
    public boolean shouldSerializeFields(Class<?> clazz) {
        return isFieldSerializable(clazz);
    }

    @Override
    public void validateDeserialize(Class<?> clazz) throws 
SerializationException {
        if (!isInstantiable(clazz)) {
            throw new SerializationException("Type '" + clazz.getName() + "' 
is not serializable.");
        }
    }

    @Override
    public void validateSerialize(Class<?> clazz) throws 
SerializationException {
        if (!isInstantiable(clazz)) {
            throw new SerializationException("Type '" + clazz.getName() + "' 
is not serializable.");
        }
    }

    /**
     * Field serializable types are primitives, {@line IsSerializable},
     * {@link Serializable}, types with custom serializers, and any arrays 
of
     * those types.
     */
    private boolean isFieldSerializable(Class<?> clazz) {
        if (isInstantiable(clazz)) {
            return true;
        }
        if (Serializable.class.isAssignableFrom(clazz)) {
            return !JRE_BLACKSET.contains(clazz);
        }
        return false;
    }

    /**
     * Instantiable types are primitives, {@line IsSerializable}, types with
     * custom serializers, and any arrays of those types. Merely
     * {@link Serializable} types cannot be instantiated or serialized 
directly
     * (only as super types of legacy serializable types).
     */
    private boolean isInstantiable(Class<?> clazz) {
        if (clazz.isPrimitive()) {
            return true;
        }
        if (clazz.isArray()) {
            return isInstantiable(clazz.getComponentType());
        }
        if (Serializable.class.isAssignableFrom(clazz)) {
            return true;
        }
        if (IsSerializable.class.isAssignableFrom(clazz)) {
            return true;
        }
        return SerializabilityUtil.hasCustomFieldSerializer(clazz) != null;
    }
}


And the RemoteServiceServlet:

public abstract class CustomRemoteServiceServlet extends 
RemoteServiceServlet {

    @Override
    protected SerializationPolicy doGetSerializationPolicy(
HttpServletRequest request, String moduleBaseURL, String strongName) {
        return CustomSerializationPolicy.getInstance();
    }
}


... and use it on your RPC service class:

public class MyServiceImpl extends CustomRemoteServiceServlet implements 
MyService {

    // ...

}

There you go, no more serialization problems, class whitelisting, use of 
IsSerializable, and so on.

Hope that helps.

Gilberto

On Friday, August 14, 2015 at 9:47:02 PM UTC-3, Guillaume Rebesche wrote:
>
> So I ran into an interesting issue today and I wanted to share it because 
> I didn't find an explanation anywhere on the internet.
> I'm not sure this issue require a fix but still it was annoying to ran 
> into.
>
> So today, my GWT application (GWT 2.7) didn't want to start for no obvious 
> reason (in Debug mode or SDM). Right after the server started, I got the 
> famous:
> com.google.gwt.user.client.rpc.SerializationException: Type 'MyClass' was 
> not assignable to 'com.google.gwt.user.client.rpc.IsSerializable'
>
> Since I didn't have any modified files and that it was working fine 30mn 
> before, I knew it was not a code issue. So I cleared all my caches and 
> tried again but still no luck. I checked my deployed folder and the gwt.rpc 
> file was there and correct.
>
> Then I dug into GWT and found out that my application was using the 
> LegacySerializationPolicy (hence the SerializationException).
>
> Turns out, I had forgotten to close the browser tab of a previous SDM 
> instance and even though I killed it from my IDE, my application was still 
> running in the browser.
> In our application we send request every 10s to check for update. So when 
> I started my server, a request was received *before* the gwt.rpc file was 
> built (and put into the deployment folder), and since GWT couldn't find 
> this file it was using the LegacySerializationPolicy and was caching it in 
> memory, so GWT would never use my gwt.rpc file...
>
> Conclusion: Never forget to close the browser tab. :)
>
> Cheers
>

-- 
You received this message because you are subscribed to the Google Groups 
"Google Web Toolkit" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.

Reply via email to