I have an enum in the client part of a GWT application and I am getting an exception when I try to run it that is related to serialization problems. Am I doing anything wrong? I read that enums are supported by GWT and I am using the last version.
The enum:
public enum AnEnum implements Serializable {
ITEM_A("Item a description"), ITEM_B("Item b description");
private String description;
private AnEnum(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
The exception:
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeWithCustomSerializer(ServerSerializationStreamWriter.java:742)
... 47 more
Caused by: com.google.gwt.user.client.rpc.SerializationException: Type '(...).client.(...).AnEnum' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.: instance = ITEM_A
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:610)
at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:129)
at com.google.gwt.user.client.rpc.core.java.util.Collection_CustomFieldSerializerBase.serialize(Collection_CustomFieldSerializerBase.java:43)
at com.google.gwt.user.client.rpc.core.java.util.LinkedList_CustomFieldSerializer.serialize(LinkedList_CustomFieldSerializer.java:36)
... 52 more
Add IsSerializable interface, a default scoped no-arg constructor, and make sure its in one of the paths listed in the source tags in your gwt.xml file. <source path="client">
I really think the third suggestion is the issue; I remember having this issue before and it was because I had a dto outside the source paths.
You can have multiple source tags.
<source path="common" />
<source path="client" />
One pattern is to put persisted objects directly under com.mysite.common, and mashups of persisted items that get transferred over the wire in com.mysite.common.dto, and of course the client gui code is in client.
package com.mysite.client;
import java.io.Serializable;
import com.google.gwt.user.client.rpc.IsSerializable;
public enum AnEnum implements Serializable, IsSerializable {
ITEM_A("Item a description"), ITEM_B("Item b description");
private String description;
AnEnum() {
}
AnEnum(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
You can try this check list:
Verify that the class has a default constructor (without arguments)
Verify that the class implements Serializable or IsSerializable or
implements an Interface that extends Serializable or extends a class
that implement Serializable
Verify that the class is in a client.* package or …
Verify, if the class is not in client.* package, that is compiled in
your GWT xml module definition. By default
is present. If your class is in another package you have to add it
to source. For example if your class is under domain.* you should
add it to xml as . Be aware that the class
cannot belong to server package! More details on GWT page: http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html#DevGuideModuleXml
If you are including the class from another GWT project you have to
add the inherits to your xml module definition. For example if your
class Foo is in the package com.dummy.domain you have to add
to the module definition.
More details here: http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html#DevGuideInheritingModules
If you are including the class from another GWT project released as
a jar verify that the jar contains also the source code because GWT
recompile also the Java source for the classes passed to the Client.
Font: http://isolasoftware.it/2011/03/22/gwt-serialization-policy-error/
i think you need a no arg constructor.
I been studying above to solve some GWT code written in 2008, when upgraded to GWT SDK 2.4.0 (with latest gxt*.jar) gives me:
[WARN] adempiereService: An IncompatibleRemoteServiceException was thrown while processing this call.
com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: com.google.gwt.user.client.rpc.SerializationException: Type 'org.idempiere.ui.gwt.client.util.AdempiereGXTUtil$LoginStage' was not included in the set of types which can be deserialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be deserialized.
at com.google.gwt.user.server.rpc.RPC.decodeRequest(RPC.java:315)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:206)
...
Caused by: com.google.gwt.user.client.rpc.SerializationException: com.google.gwt.user.client.rpc.SerializationException: Type 'org.idempiere.ui.gwt.client.util.AdempiereGXTUtil$LoginStage' was not included in the set of types which can be deserialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be deserialized.
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deserialize(ServerSerializationStreamReader.java:581)
That notorious class is as follows (edited to follow ideas given in this thread):
public class AdempiereGXTUtil {
public enum LoginStage implements IsSerializable, Serializable {
LOGOUT,
LOGIN,
ISLOGGEDIN,
ROLES,
WRONGUSER,
WRONGROLE;
LoginStage(){
}
};
}
Thinking about Andrej's answer to add type to white-list but enum is not some new myType, right? Anyway here is some reference in the codebase (non-relevant fields removed):
public interface AdempiereService extends RemoteService {
public static final String SERVICE_URI = "adempiereService";
public static class Util {
public static AdempiereServiceAsync getInstance() {
AdempiereServiceAsync instance = (AdempiereServiceAsync) GWT
.create(AdempiereService.class);
return instance;
}
}
...
public LoginStage getLoginStage();
with:
public interface AdempiereServiceAsync {
...
public void getLoginStage(AsyncCallback<LoginStage> callback);
Originally the AdempiereGXTUtil did not implement IsSerializable, Serializable nor has empty constructor but putting them in above, and cleaning out project in Eclipse does not change the same errors. Eclipse version used is Indigo on Java 1.6 in a Mac Lion environment. Hoping to get more from this thread, which by the way is amazing in its technical depth.
Only names of enumeration constants are serialized by GWT's RPC. Field values are not serialized.
GWT:Server Communication:Serializable Types
In this case, Enum cannot be in the class. You have to create an external Enum.
In Gwt 2.9, I also had a "was not included in the set of types which can be serialized" error on a class that contained a field of type java.util.EnumSet of a custom enum class.
It turned out the issue was not my custom enum, but the EnumSet itself. After replacing the EnumSet with a HashSet or LinkedHashSet, serialization worked.
Maybe this is related to this issue: https://github.com/gwtproject/gwt/issues/3319
See http://www.gwtproject.org/doc/latest/DevGuideServerCommunication.html#DevGuideSerializableTypes:
A type is serializable and can be used in a service interface if one
of the following is true:
The type is primitive, such as char, byte, short, int, long, boolean,
float, or double. The type an instance of the String, Date, or a
primitive wrapper such as Character, Byte, Short, Integer, Long,
Boolean, Float, or Double. The type is an enumeration. Enumeration
constants are serialized as a name only; none of the field values are
serialized. The type is an array of serializable types (including
other serializable arrays). The type is a serializable user-defined
class. The type has at least one serializable subclass. The type has a
Custom Field Serializer
In your case the type is an enumeration, so it is meant to be serializable.
These days GWT has 2 serialisation policies: LegacySerializationPolicy and StandardSerializationPolicy.
The LegacySerializationPolicy has an issue serialising enums unless they implement IsSerializable.
Normally StandardSerializationPolicy will be used unless the SerializationPolicyProvider cannot find the *.gwt.rpc file for some reason. If it cannot find the *.gwt.rpc file then it will write a warning that you will most likely get serialisation issues so I would suggest that you start looking in the error log to see if it had issues finding the *.gwt.rpc file and if so fix that.
Also on a side note you should not be mutating Enums, I recall that Joshua Bloch writes about that in his book Effective Java.
a) You definitely need a no-op constructor for serialization.
b) You can either extend GWT' IsSerializable class or, if you want to use Java's Serialization interface you must setup a policy to allow this. There's a post related to this at How do I add a type to GWT's Serialization Policy whitelist?. Also, check the GWT sight for more information on IsSerializable vs. Serializable.
Related
I'm using Kotlin with Apache Beam and I have a set of DTOs that reference each other and all serialize great for any encoder with Kotlinx Serialization. When I try to use them with Beam I end up having issues because it's looking for all objects, type parameters and nested objects to implement the Java Serializable interface. Problem is, I'm not in control of that with all object types because some come from 3rd-party libraries.
I've implemented my own CustomCoder<T> type that uses Kotlinx Serialization but then I run into issues with my custom coder not being serializable, particularly due to the Kotlinx Serialization plugin-generated Companion object serializer not serializing. Since it's compile-time generated code I don't really have control over that and I can't flag it as #Transient. I tried implementing Externalizable on the coder and it fails as soon as I pass a type argument for T that doesn't implement Serializable or has a nested type argument that doesn't.
Also, Kotlinx Serialization is nice because it doesn't use reflection. It would make a lot of my current headaches disappear if I could just swap out the serialization mechanism somehow and not have to rely on standard Java serialization methods at all or somehow implement Externalizable in a way that just calls out to my own serialization mechanism and ignores the type parameter. Are there any solutions? I don't care how hacky it is, even if the solution involves messing with stuff in the Gradle build config to override something. I'm just not sure how to go about it so any pointers would be a great help!
Alternatively, if I abandon Kotlinx Serialization, are there any simple solutions to make any arbitrarily complex data type serialization just work with Java, even using reflection, without a lot of custom, manual work to handle encoding and decoding? I feel like maybe I'm just missing something obvious. This is my first project with Apache Beam but so far the google is little help.
Mybe late, I develop an annotation processor called beanknife recently, it support generate DTO from any class. You need config by annotation. But you don't need change the original class. This library support configuring on a separate class. Of course you can choose which property you want and which you not need. And you can add new property by the static method in the config class. The most power feature of this library is it support automatically convert a object property to the DTO version. for example
class Pojo1 {
String a;
Pojo b; // circular reference to Pojo2
}
class Pojo2 {
Pojo1 a;
List<Pojo1> b;
Map<List<Pojo1>>[] c;
}
// remove the circular reference in the DTO
#ViewOf(value = Pojo1.class, includePattern = ".*", excludes={Pojo1Meta.b})
class ConfigureOfPojo2 {}
// use the no circular reference versioned dto replace the Pojo1
#ViewOf(value = Pojo2.class, includePattern = ".*")
class ConfigureOfPojo2 {
// convert b to dto version
#OverrideViewProperty(Pojo2Meta.b)
private List<Pojo1View> b;
// convert c to dto version
#OverrideViewProperty(Pojo2Meta.c)
private Map<List<Pojo1View>>[] c;
}
will generate
// meta class, you can use it to reference the property name in a safe way.
class Pojo1Meta {
public final String a = "a";
public final String b = "b";
}
// generated DTO class. The actual one will be more complicate, there are many other method.
class Pojo1View {
private String a;
public Pojo1View read(Pojo1 source) { ... }
... getters and setters ...
}
class Pojo2Meta {
public final String a = "a";
public final String b = "b";
public final String c = "c";
}
class Pojo2View {
private String a;
private List<Pojo1View> b;
private Map<List<Pojo1View>>[] c;
public Pojo1View read(Pojo2 source) { ... }
... getters and setters ...
}
The interest things here is you can safely use the class not exist yet in the source. Although the compiler may complain, all will be ok after compiled. Because all the extra class will be automatically generated just before compiled.
A better approach may be to compile step by step, first add #ViewOf annotations, and then compile, so that all the classes that need to be used later are generated. Compile again after the configuration is complete. The advantage of this is that the IDE will not have grammatical error prompts, and can make better use of the IDE's auto-complete function.
With the support of using generated DTO in the configure class. You can define a Dto without circular reference just like the example. Furthermore, you can define another dto for Pojo2, and remove all property reference the Pojo1 and use it to replace the property b in Pojo1.
I'm encountering an error with a Spring Data repository as it attempts to resolve a property expression:
public interface ContractRepository
extends MongoRepository<Contract,String> {
public List<Contract> findByCodeBindings(String binding);
}
Here's the relevant parts of Contract:
#Document(collection="CONTRACTS")
public class PersistentContract extends BaseContract {
#PersistenceConstructor
public PersistentContract(String name, Version version, Code code) {
super(name, version, code);
}
}
Code is an interface implemented by CodeImpl. It contains a property bindings, which has a getter and setter in Code. So the query's property expression is designed to find those contracts with a nested Code document containing a given binding. So far, so good.
However, the problem is an IllegalArgumentException is getting thrown:
java.lang.IllegalArgumentException: No property bindings found on my.company.Code!
org.springframework.data.mapping.context.AbstractMappingContext.getPersistentPropertyPath(AbstractMappingContext.java:225)
Debugging that section of code shows that Spring Data is picking apart the expression and determines there's a property of type Code. However, because Code is an interface, it has no properties listed.
Is there a means to hint to Spring Data that either Code has this property or that CodeImpl is the actual type of the code property? I'm surprised that the library doesn't attempt to parse the getters or setters of the interface.
This is using spring-data-commons 1.5.1.RELEASE and spring-data-mongodb 1.2.1.RELEASE.
Appreciate the help.
My solution was to avoid interfaces at all in the persistent object. So BaseContract became the following:
public abstract class BaseContract<T extends Code> {
public abstract T getCode();
}
And PersistentContract was implemented in terms of concrete classes:
public class PersistentContract extends BaseContract<CodeImpl> {
}
This seems to strike the right balance between coding against interfaces in the base class and satisfying Spring Data's need for concrete classes.
I have some Serializable Objects which I use with GWT's RPC mechanism.
I decided to make them all sub-class an Object containing common fields such as "id", "revision" etc.
However, I've noticed that GWT does not serialize fields of the super-class, so I just get every super-class field as null on the client-side.
How can I get the super-class fields serialized as well without having to write a CustomFieldSerializer for each and every one of my Serializable classes? Is it possible?
Example:
public class Super {
private String id;
public String getId() {
return id;
}
}
public class Sub extends Super implements Serializable {
private String name;
// more stuff here
}
// on the client side, inside an AsyncCallback
onSuccess(Sub sub) {
assert(sub.getId() != null);
}
So, when I send this through GWT's RPC mechanism to the client-side, I get a null value in the 'id' field of any instance of Sub. I ensured that in the server, id is not null. I also tried to make the super-class implement Serializable, without luck.
Any advices welcome.
For serialize any class in gwt you have to implements Serializable in super class.
To pass a bean you have to fulfill the following requirements (from GWT site):
1.It implements either Java Serializable or GWT IsSerializable interface, either directly, or because it derives from a superclass that does.
2.Its non-final, non-transient instance fields are themselves serializable
3.It has a default (zero argument) constructor with any access modifier (e.g. private Foo(){} will work)
The problem may have different causes.
1.Verify that the class has a default constructor (without arguments)
2.Verify that the class implements Serializable or IsSerializable or implements an Interface that extends Serializable or extends a class that implement Serializable
3.Verify that the class is in a client.* package or …
4.Verify, if the class is not in client.* package, that is compiled in your GWT xml module definition. By default is present. If your class is in another package you have to add it to source. For example if your class is under domain.* you should add it to xml as . Be aware that the class cannot belong to server package!
5.If you are including the class from another GWT project you have to add the inherits to your xml module definition. For example if your class Foo is in the package com.dummy.domain you have to add to the module definition.
6.If you are including the class from another GWT project released as a jar verify that the jar contains also the source code because GWT recompile also the Java source for the classes passed to the Client.
If you want the data in Super to be serialized, you must make it Serializable.
I wonder if there is any support for different versions of class in JAXB.
My thoughts about it: xml is kind of persistence object of class (serialized value) but class object can be changed due to development (e.g. extending the functionality). Is there any way to know which version of class is stored in persistence (read: xml) using only JAXB API?
For me it seems convenient to store class version - like it's done in standard java serialization mechanism (I mean serialVersionUID) and provide functionality to map xml on class even in case of different version (e.g. adding in XmlAdapter information about version of class stored in xml). By default, if version of class in xml and in runtime differs - throw InvalidClassException.
Example:
We have class Test as follows:
#XmlRootElement
#XmlAccessorType(value = XmlAccessType.FIELD)
public class Test {
private Long time;
private Test () {};
}
assuming that time is UNIX time in millis.
This code was released on production and this class was persisted in the database as xml.
Next release shows that it was not good choice to use Long as time representation and it was changed to Date:
#XmlRootElement
#XmlAccessorType(value = XmlAccessType.FIELD)
public class Test {
private Date time;
private Test () {};
}
Now there are two ways - either to migrate persisted data or to write xml adapter which will handle Long time and apply it to the Date time.
If we choose the second way it would be great if JAXB API provides class version which were stored in xml (assuming if no class version is specified in class = 0 version) and we add new version of class explicitly (either by annotation or by static field):
#XmlRootElement
#XmlAccessorType(value = XmlAccessType.FIELD)
#XmlClassVersion(value = 1)
public class Test {
private Date time;
private Test () {};
}
or
#XmlRootElement
#XmlAccessorType(value = XmlAccessType.FIELD)
public class Test {
private static final long xmlSerialVersionUID = 1;
private Date time;
private Test () {};
}
and JAXB will provide XmlAdapter as follows:
public abstract class XmlAdapter<ValueType,BoundType> {
protected XmlAdapter() {}
public abstract BoundType unmarshal(ValueType v, long classVersion) throws Exception;
public abstract ValueType marshal(BoundType v, long classVersion) throws Exception;
}
In order to support multiple versions, of course, we need to implement such adapter and handle different versions explicitly.
Clearly, then, JAXB will add special information about class in xml and will generate xml on the latest class version.
NOTE: the point of the example above that we have 2 different representations of class in the persistence simultaneously but still can map them to the version of class available in the runtime.
JAXB stands for "Java Architecture for XML Binding", so, it's about binding objects fields values to XML elements/attributes, and not about serializing java objects. In you read for example this article, you see that it says
javax.xml.bind, contains classes and interfaces for performing
operations such as unmarshalling, marshalling, and validation
Java object serialization is another thing, and it's related to the serialVersionUID that you mention in your question.
If you are using JAXB you would be persisting xml and not the java object. If you were persisting java object it would be serialization. Jaxb transformation tries to bind the xml values to the class attributes. As long as the transformation prerequisites work, there shouldn't be a problem. Other libraries like JIBX, try to access bytecode directly. The class version may be an issue in such a case.
I am currently using Jackson 1.4.2 and attempting deserialization of code values (unique identifiers for type information) that are passed from our UI back to the Java controllers (Servlets).
There are multiple types (e.g. ABCType, XYZType, etc.) that all extend from an AbstractType, but each concrete type has a static factory method that takes as a single parameter, a unique identifier, and returns the type object (name, associated types, description, valid acronyms, etc.) represented by that identifier. The static method within each concrete type (e.g. XYZType) is annotated with #JsonCreator:
#JsonCreator
public static XYZType getInstance(String code) {
.....
}
The problem that I am seeing though is an exception thrown by Jackson's mapper trying to deserialize the json to those types:
Caused by: org.codehaus.jackson.map.JsonMappingException: No default constructor found for type [simple type, class com.company.type.XYZtype]: can not instantiate from Json object.
What am I missing here of the #JsonCreator annotation to static factory methods (or is it to do with Jackson 1.4.2 struggling with the concrete types extending from an AbstractType?)?
The annotation #JsonCreator requires the annotation #JsonProperty. This Jackson wiki page gives little information but does offer sample code:
#JsonCreator
public Name(#JsonProperty("givenName") String g, #JsonProperty("familyName") String f)
{
givenName = g;
familyName = f;
}
You'll find a more detailed explanation at this blog post.
Your sample code should therefore look something like this:
#JsonCreator
public static XYZType getInstance(#JsonProperty("someCode") String code)
{
...
}
Problem is that Jackson only sees the declared base type, and does not know where to look for subtypes.
Since full polymorphic type handling was added in 1.5, what you need to do with 1.4 is to add factory method in the base class and dispatch methods from there.