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.