In xstream for java, is there a way to deserialize an object by ensuring that it goes thru a specific constructor with parameters?
XStream (or deserialization in general) doesn't call constructors. (Except in the rarely used Pure Java Mode, when it calls the default constructor.)
You need to use the readResolve() method if you want to initialise transient fields.
However you can write your own converter, and then you can do whatever you want. This approach works best if you have one specific class that you want to apply this to.
Related
So I have a POJO class let´s call it: InnerDomainObject.
Then I have an object representing this object, with a few more fields, for communication towards different clients (it s an API DTO): OuterDomainObject
Because the DTO has in fact all of the POJOs fields, I made OuterDomainObject inherit from InnerDomainObject.
Now I need to somehow cast InnerDomainObject to OuterDomainObject --> not possible.
I want to avoid writing a constructor iterating through all the fields.
I want to avoid writing useless code.
I just want OuterDomainObject to be created out of InnerDomainOBject´s values and then add some to it before sending it to the client.
What´s the best way of doing this ?
You sound like you are using the Adapter Pattern. You shouldn't need to cast an InnerDomainObject to an OuterDomainObject. You should use composition: the OuterDomainObject should hold a reference to an InnerDomainObject, which will likely be passed into a constructor. When a client invokes a method on an OuterDomainObject, if that method exists in InnerDomainObject, the OuterDomainObject should call that method on its instance of InnerDomainObject. Instead of casting an InnerDomainObject foo to an OuterDomainObject, just create a new OuterDomainObject and pass in foo: new OuterDomainObject(foo). You will need to write some simple glue code, but the result is very clean.
Serialization makes sense as an instance method - an object might reasonably be able to serialize itself. An object should only ever be in a valid state, and all valid states of an object should be permissible to serialize. There is nothing invalid about this idea.
But deserialization does not make sense as an instance method. No part of an object's state should have any bearing on the process of constructing another object from data. There is no class foo such that you need a constructed foo in order to construct a foo.
So my question is, does standard java have a pre-existing set of interfaces/facilities to facilitate static deserialization? If you implement the instance-based approach, your deserialization "just works" (as much as anything does) with anything that works with Java's default deserialization ability.
Is there anything built in, to use classes as factories for objects of that class, constructed from serial data? Is there anything in Java I could pass a class to, such that this facility would know to call some static method to deserialize to construct an object from its flat form?
The deserialization instance method readObject is private. There is no way to call it from the outside. You could call it from one of your instance methods, but that would be very strange and I'd question why you'd be doing that in the first place. You say:
No part of an object's state should have any bearing on the process of constructing another object from data.
True, but I don't see why you think this would be an issue. There's no way you could call readObject from the outside (unless you call it from some other public method, which as I said, is kind of iffy) on an instance that you have already created. When you deserialize, you will most probably be using ObjectInputStream, which will use the no-args constructor to create a new instance, and then will hydrate that object using the data from the stream (when you call ObjectInputStream#readObject). So there is no question of the state of the instance affecting deserialization, because what you get back is an instance created from the serialized data (as Object, but you will then cast it to the concrete type).
In effect, readObject behaves somewhat like a constructor, except that it uses previously-serialized data to create an instance of an object. Extending the analogy, your question wouldn't make sense because you would be asking "Why does creating an object using the constructor have anything to do with the state of the instance?". The question of state doesn't even apply because you don't even have an instance! Similarly, state doesn't come into play with readObject because can never* deserialize and create an instance by using an existing instance.
If you want greater control over serialization, you can override readObject and writeObject from Serializable within your class if you want to handle things in a special way. You can exert greater control over how the data is written out by implementing Externizable and providing implementations for readExternal and writeExternal.
In your second question you're wondering what the "something" is that calls readObject. The "something" is reflection; ObjectInputStream will check to see if the class has a readObject method. If you've provided your own implementation, it will call that. Otherwise it will call defaultReadObject (which contains the logic for default serialization).
As far as built-in factories for deserialization, there isn't anything and I haven't really felt a need something since the standard serialization/deserialization approach seems to work well.
If you want more information on this, I suggest taking a look at the serialization specification for a comprehensive and in-depth view of how Java tackles serialization, and specifically Object Input Classes for your particular question.
*The only way state comes into it is if you do something strange like calling the readObject method from some other instance method (which would have to take in an ObjectInputStream), and then you have custom logic that performs deserialization based on the state of the existing instance. In other words, the only way the object's state has any bearing on deserialization logic is if you explicitly write it that way. Again, as I mentioned before, that would be very strange code, with a whole lot of caveats and of minimal value.
I am trying to use flexjson library. But in my object I have to use:
com.google.api.client.util.DateTime which do not have no parameters constructor. I always get NoSuchMethodException with message: Flexjson will instantiate any protected, private, or public no-arg constructor. I have sources and trying to do something with that, here is the code:
constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
return constructor.newInstance();
Exception is being thrown in clazz.getDeclaredConstructor() due to lacking empty constructor. What is the best approach to find constructor with let's say those signature:
DateTime(long timestamp)?
Have anyone encounter this kind of problem with this library? Maybe you can suggest to use other one. I am using it to serialize objects generated by Google Cloud Endpoints. Maybe I can do that with different approach?
You don't have to change the source code of Flexjson to do this. The way to handle this is to create your own implementation of ObjectFactory and register that for the type you are binding into. From there you can instantiate it however, you desire. It's easiest to subclass BeanObjectFactory and override the method instantiate(). In there you can do whatever you want to create an instance of an object you wish. By subclassing BeanObjectFactory it will take care of binding the individual properties from the JSON into your object using the setter/getter of that object. If your object doesn't support property methods you might find it easier to implement ObjectFactory and manually setting the values on that object from the JSON. There is lots of documentation on the Flexjson website about building ObjectFactories.
Then you can register your ObjectFactory to that data type using:
new JSONDeserializer<SomeObject>()
.use( DateTime.class, new DateTimeObjectFactory() )
.deserialize(json);
I have a class that implements Serializable, it's part of a bigger mesh of objects, it contains a Constructor field, but when it's the Constructors turn to be serialized it throws the NotSerializableException.
I guess I'll have to write the logic myself and recreate the constructor myself every time I deserialize the containing object, but why the heck on earth would the designers of Java wanna create such hassle in the first place? I realize that the ClassLoader is needed to figure out the identity of a class, and that the ClassLoader itself will not be serialized and deserialized, but shouldn't the constructor remember the string arguments used to create it?
Yes, as you realized Constructor is not serializable.
You need to make the Constructor field transient and restore it manually, when needed.
Yes, the Java designers could have made the Constructor class serialized down to the class name and argument list, but that would open a huge can of worms, basically boiling down to the fact that in any given JVM there can be an arbitrary number of classes with that name and there's no sane way to know which one to use when deserializing such an object.
I have a class called A and I need to create a new object of that class without calling its constructor. I want to set all its attributes through reflection.
Can I redefine the constructor of class A using reflection?
Or is there any way other way to do this?
In the Sun/Oracle JVm you can use Unsafe.allocateInstance(Class). Otherwise you have to generate byte code to create the instance without calling a constructor. You could use ASM for this. You cannot create an instance without a constructor using Reflection alone.
BTW: You can define a new method using byte code manipulation, but to add a constructor, you have to change the class before it is loaded. (This is tricky to do)
Invoke the object with the constructor that takes the least amount of arguments; using dummy arguments. Then proceed to manipulate the object however you like.