I have an object from a class I cannot modify.
The object has a circular dependency.
I would like to serialize the object, but I don't have access to java source code, as it's in a library.
In C++ I could create a subclass, override the virtual methods, then cast down to get the desired behavior. In Java this is not possible.
What options do I have besides creating a new POJO class and copying over every field by hand?
Serialization using Serializable is a bit smelly anyway. I'd prefer using an external serializer, using either JSON (e.g. Jackson, GSON) or a binary format (e.g. Kryo). Either way, you can write custom serializers in all of these that resolve your circular dependencies.
I'd opt for Jackson, even if you are going to be the only one reading/writing your objects. Many advantages, up to and including:
Diagnosing/debugging the serialized JSON makes life easy.
Staying on this well-trodden path means solutions to any questions are a Google away, e.g., http://www.baeldung.com/jackson-deserialization
Related
I'm trying to make my classes Serializable. All of my classes are, but still it throws me NotSerializableException for some other classes that I can't find it's usages (e.g. com.sun.java.swing.plaf.windows.XPStyle, WClipboard).
What can I do and how can I bypass these classes when serializing or make them Serializable?
SOLVED
The problem was in LookAndFeel I have used in my JFrames and JDialogs (problem with XPStyle). Second one (WClipboard), it was used by third party class I got from here. This class uses Clipboard.
I made Clipboard field transient and LookAndFeel I couldn't manage, just by deleting it.
If you do not want the data to be serialized for persistence or transfer, than you can declare those transient
However, if you need the data in those Objects (classes) to be persisted, transported via TCP / UDP, etc. than you might want to extend the class, and implement your own interpretation of it, so that you can then declare your extended class Serializable.
A final option might be to use a different method of Serialization, such as those provided by FST, Kryo, etc. Often times these Serialization libraries can use Reflection to Serialize Objects that the default Java implementation cannot.
What happens if I serialize a Map(or List) with a java version, and I try to deserialize it with other java version, where the serialVersionUID changed? I suppose it will fail.
If you create a lib for others to use what will be the preferred way of serializing objects, using Java Objects like Map, List or using an array of self made objects?
e.g.
List<MyObject> or MyObject[]?
Map<String, MyObject> or MyObject2[] (MyObject2 contains the key and MyObject)?
If you control the class and if you did not change the serialVersionUID also deserialization of an instance of a class from a older version is possible. There for java provides a concept which is called binary compatibility. Most of the flexibility of binary compatibility comes from the use of a late binding of symbolic references for the names of classes, interfaces, fields, methods:
http://docs.oracle.com/javase/7/docs/platform/serialization/spec/version.html
So core classes from java e.g. HashMap, ArrayList, Vector... will be deserializable even if the class will be involved in a future version of java.
If you wish to control versioning in your own class, you simply have to provide the serialVersionUID field manually and ensure it is always the same, no matter what changes you make to the classfile.
See also this article:
http://www.oracle.com/technetwork/articles/java/javaserial-1536170.html
Yes, you are correct, deserialization with changed serialVersionUID will fail. Version of JDK doesn't matter here.
If you create a lib for others to use what will be the preferred way
of serializing objects, using Java Objects like Map, List or using an
array of self made objects?
You can serialize objects to some more portable format, like plain text with (e.g. JSON, XML). You may take a look at JAXB or XStream.
But keep in mind, that main usage of serialization is to transfer objects over the network. If you would like to store some state you typically should use a database. Serialization to bytes is useful mainly for short-lived objects (because as you noticed, object may change, and thus serializationVersionId may change also).
Hope it helps.
I have successfully started using GSON to serialize and de-serialize a hierarchy of objects in my Android application.
Some of the objects being serialized have members which I must mark as transient (or otherwise use alternative GSON annotations to prevent them being serialized) because they are references to objects that I do not want to serialize as part of the output JSON string. Those references are to objects which must be separately constructed by some other means.
Once the structure is de-serialized back into Java objects, at some point I need to fill in those references. I could easily do this perhaps by using a series of setXXX() type methods, but until that is done, those objects are in an incomplete state. What I am therefore wondering is whether there is a more robust approach to this.
Ways I have thought of so far:
Have the objects throw a RuntimeException (or something more suitable) if they're in an incomplete state; that is, if they're asked to do some work when some initialization method wasn't called.
Separate out the serializable bits into a separate data model object. In other words, take out the stuff that can't be serialized. After GSON de-serialization, build up my 'real' objects using those data objects in their composition. This seems to defeat the convenience of using GSON somewhat.
Write a custom deserializer for GSON to handle the special creation of those objects.
Check out https://github.com/julman99/gson-fire
It's a library I made that extends Gson to handle cases like Post-serialization and Post-deserialization
Also it has many other cool features that I've needed over time with Gson.
I would likely take the second approach, because as I typically design my applications, anything that needs to be serialized/deserialized is really just plain old data, or POJOs if you prefer. If I find myself needing to customize/configure the serialization API to do what I want, I tend to simplify what's being serialized, so the serialization API doesn't need the extra configurations.
So, if I have a more complicated data model, parts of which aren't to be serialized/deserialized, then I extract from it a simpler set of POJOs, as a conceptually separate data model to participate in the serialization/deserialization. This does then indeed require an extra step to map between the two data models, but that's usually pretty simple, also.
If the third approach is preferred, then note also the Instance Creator feature, as it can provide another useful hook into customizing the deserialization process.
Is there a generic way to cache any type of object (be in a java class, or a word document etc.) to memory or disk?
Is simply serializing the object, and retaining the file extension (if it has one) enough to rebuild the object?
You seems to be using the word Object to describe 2 different things.
If your object is a Java object then having that object implement the Serializable is enough if you then use the java methods to serialize/de-serialize the object.
If you want to cache arbitrary data from the filesystem, the best way is to read it in an byte array(Or ArrayList). Then you can just write the array back to the disk or where you want it.
If you're talking about the inbuilt Java serialization, then you wouldn't even need to retain the file extension. The serialized form has enough information such that the deserialization process will produce an identical object without any additional help. I suppose that depending on how your code is structured, though, you might need to store some metadata for your own benefit so that you know what to cast the resulting Object as.
Note that Java serialization doesn't seem to fit your requirements, though - it cannot serialize any type of object, only those that implement Serializable. Perhaps you need to think a little more about what you mean by "simply serializing the object", since that's the rub.
No.
There is a class of objects which cannot be deserialized in a meaningful way. Think of an open network connection which is in the middle of transferring a file. You can not store that to disk, close your app, open your app, deserialize that connection and expect that it "just continues".
Java has an interface Serializable which indicates that an object can be serialized. It's up to you to ensure that is indeed possible. Typically an object is Serializable if all the data it holds is Serializable, or that data which is not Serializable is marked transient.
This is not to say that you could not, theoretically, dump the memory contents to a file as a byte stream, and read it back again later. You could build something like that I suppose. But to expect that it works is a different thing altogether.
In short, it is not possible to serialize any type. However, there is a generic way to serialize Java objects which are marked to be Serializable.
Not sure what you mean by "or a word document". Serialization can be used for disk caching, not sure what the purpose of using it in memory would be since it would probably be far faster to simply keep the original object.
A more robust solution might be ehcache it can manage the size of the cache as well as moving it between memory and disk.
If you're wondering about the cross platform (disk or memory) persistence part of the question, look at Java's Preferences class.
My, what a lot of answers!
Any object can make itself serializable by implementing java.io.Serializable.
But:
A default serialiser is implemented in ObjectOutputStream, which simply walks the object tree. This is fine for simple javabean type objects, but it can have undesirable effects such as system objects being serialised (I once inspected a serialised java object file and found that it was including all of the system timezone objects). And, of course, if your object has objects inside it that are not serializable (and not transient), then ObjectOutputStream will throw an exception.
(actually, even for JavaBean objects the default serializer it awful - the default serializer emits the classname of java.lang.String for every string field.)
So if your object is complicated, then you really should implement Externalizable and write a serialiser and deserializer with some smarts.
http://download.oracle.com/javase/6/docs/platform/serialization/spec/serial-arch.html#7185
So basically - no, you can't serialise any old object. You have to design object that are intended to be serialised and, ideally, that have some smarts about how they get themselves to and from a stream.
You cannot serialize any object in Java. Moreover, Java uses shallow copying(or is it called something else) for serialization, so if you want to seialize something like a HashMap, it might not save your data.
I've got a complex object which is being managed by the LCDS DataServices data management and being created/updated etc using custom assemblers. The vast majority of the object hierarchy is being serialized/deserialized correctly but I've hit a stumbling block when it comes to serializing immutable java classes.
In a java only world I would use the java writeReplace and readResolve methods as this excellent blog describes: http://lingpipe-blog.com/2009/08/10/serializing-immutable-singletons-serialization-proxy/
This is how I originally wrote my java class, expecting livecycle to call the writeReplace method and duly replace the immutable class with a mutable one for serialization. However it would appear that lcds knows nothing of the writeReplace method and will only call readExternal/writeExternal ignoring readResolve and writeReplace.
Firstly, have other people found this to be the case, or am I missing something?
Secondly, has anyone come up with an appropriate method to deserialize actionscript classes into either immutable objects or singletons?
Many thanks
Yes, it's a common problem. Adobe recommend that the Java type that has immutable properties implements Externalizable and the equivalent ActionScript type implements IExternalizable.
There is no plan to handle the writeReplace and readResolve, but you can ask for a feature request http://bugs.adobe.com/jira/browse/BLZ
When implementing your custom serialization take care that you will lose some benefits like compressing numbers and identifying duplicate strings. One idea is to take a look on the actual serialization mechanism and to modify it accordingly.
However, if you are interested just in serializing the read only properties this enhancement was implemented in the BlazeDS, take a look here: http://bugs.adobe.com/jira/browse/BLZ-427
shortest and most comprehensive answer i found: http://expertdevelopers.blogspot.com/2010/07/serializable-vs-externalizable.html