Can I achieve this using Serialization? - java

I have a class named Database that is defined and contains some data in it's fields.
Now, I create an object of that class as
Database d1 = new Database();
Now, I make changes to those data values of d1 such that whenever I create another object of Database say 'Database d2', this object has the updated values of the data. That means, we need to be able to change the class definition using an object of that class.
Can this be achievable?

I think you might want to implement a copy constructor in your java code, you can do this:
class Database{
Filed field; // some field
Database(){
}
Database(Database db){ // copy constructor
this.field = db.field.clone();
}
}
Database d2 = new Database(d1)
Then d2 will have all the filed updated by d1.

"That means, we need to be able to change the class definition using an object of that class."
Really? You don't change the values in the fields of an instance of a class by changing the classes definition. The class definition is ... the source code / compiled bytecodes.
But if you DO change the class definition, you are liable to find that the new version of the class cannot deserialize instances that were serialized using the old version of the class. (Details depend on the precise nature of the changes ...)
More generally, Java serialization is not a good option for databases:
it is slow,
it is not incremental (if you are loading / saving the entire database)
it doesn't scale (if you are loading the entire database into memory)
it doesn't support querying (unless you load the entire database into memory and implement the queries in plain Java), and
you run into lots of problems if you need to change the "schema"; i.e. the classes that you are serializing / deserializing.
But modulo those limitations, it will work; i.e. it is "achievable".
And if you are really talking about how to change the state of your in-memory Database object, or how to create a new copy from an existing out then:
implement / use getters, setters and / or other methods in the Database class,
implement a copy constructor, factory method or clone method that copies the Database object state ... to whatever depth you need.
All very achievable (simple "Java 101" level programming), though not necessarily a good idea.

Related

Should data objects be considered immutable?

I have defined a data object that maps to the fields stored in DynamoDB table. Whenever I do a load by specifying the class name such as dynamodbmapper.load(Item.class, hashkey). Should I be making the Item class fields final? Conceptually should this object be immutable? I don't want any service code to modify this object.
Yes, if you don't want any service code to modify this object then this seems like a good idea in general. Only viable for you if DynamoDB Java library supports creating instances via costructor args only, no direct field access or setters - it may not (I dunno).

Android classes and persistence

I know about Android data storage options and have tried most of them out. But I am not sure how to decide which of those methods would be best for me. I have what I consider a pretty well defined class hierarchy with subclasses, with each class having several member property variables and arrays of other subclasses... on paper. But how do I make it persistent? And keep the object-orientation in tact? For instance, if I have the following class
MyClass
- private String s1
- private ArrayList<MySubclass1> subclassList
- public get/set s1
- public get/set subclasslist
Well, this is great for oo, and I can create getters and setters for the member variables, but they aren't persistent. I'll have to take snapshots of the data at certain times to ensure the data does persist. The other option is to use all database storage and get rid of the private member variables and then just use public methods that read and write from the database. This is great for persistence, but I lose that finely structured object orientation. And that ArrayList gets kind of funky. I will have to do stuff like
MyClass myClass = new MyClass();
MySubclass1 mySubclass1 = new MySubclass1();
myClass.AddNewSubclass1ObjectToSubclassList(mySubclass1);
instead of
MyClass myClass = new MyClass();
MySubclass1 mySubclass1 = new MySubclass1();
myClass.subclassList.Add(mySubclass1);
And I would have to write methods for count, remove, indexOf, and all of the other great methods that come with ArrayLists.
So, have I missed something obvious? Am I making this harder than it really is? What is the best way to deal with this?
For convenience you can use some object serialization library, e.g.:
Object to XML Marshaling - Simple XML serializer
Object to JSON Marshaling - Google Gson
Then you can persist the result of marshaling in a file in order to restore your objects later. I think Internal Storage is best way for this.

Java:Immutability and serialization

When I have an immutable parent class A that is NOT final, and another class B extends it(B is mutable), is there any way the immutability of A can be affected because of serialization?
I wrote a small program to serialize an object, changed its state in the program, and then de-serialized it. I got the object back in the form in which it was serialized. So I am wondering is there any way I can alter A's immutability by serializing it?
It depends on exactly what you are asking. If you just want to get a different value back than what you put in, then yes, you can do that through serialization. The serialized data is completely detached from the instance of A that exists in memory. When Java reconstructs an object from the serialized data, it doesn't know or care anything about the original instance of A that was used to create that data. It is simply constructing a data-structure in memory based off of the blueprint provided in the serialized information.
So if you want to modify what you get back when you reconstruct A, you can do so by manually modifying the binary serialized data. Doing so will require a good understanding of Java's serialization format, but it can certainly be done.
Though if you are asking if there is any way to modify the original instance of A through serialization (as in, to somehow get the same object to change in value, without constructing a new instance via deserialization), then the answer is no, you cannot. Serialization simply creates a snapshot of the object's current state. Deserialization creates a new object instance that is completely detached from the source instance. So while you might manually change the value, the new object with the new value will still be immutable once it has been deserialized.
And if you are asking if there a way to serialize an instance of immutable class A and then deserialize the data as something that identifies as an instance of class A but happens to be mutable then the answer is also no. The serialized data specifies what class of object is being represented, but the class definition itself is not serialized. So you could change the specified class such that you serialize an instance of A and then deserialize an instance of mutable class B, but that's not the same as getting back a mutable instance of A.
You can't alter its immutability (the class will still be immutable) but you can alter its values by editing the serialized information.
You can also alter it through reflection, immutable isn't some kind of magic protection, it's just creating a class without mutators to help overal program stability. Although variables should probably be final, that's not even necessary--to be immutable you simply have to always return the same value for all of your methods.
Anyway, if you are going to extend an immutable class, you probably want your extension to be immutable as well--if not chances are you don't really want to extend the class, perhaps you just want to encapsulate it (is there an is-a relationship or a has-a?)
When you serialise an object, that object does not change whether it is immutable or not.
When you de-serialise a new object, its is a reconstruction of the first object based on the information recorded and how you do the de-serialisation.
For example, if you have an immutable class and a field is transient, the de-serialised copy will not have that field set (you made it transient)

Java serialization, UID not changed. Can I add new variables and method to the class?

I have a class that is serialised. Now I need to add a new variable into the class, with setter and getter methods. This class is sent over wire in RMI.
Without changing the UID, can I add new parameters and getter and setter methods for it? I tried to write an example class that is sent over wire, and did not change the UID, and added new parameters and getter and setter methods for it. On the other end, I tested it and I still got the values properly. I had assumed, if I add new parameters, getter and setter methods, I need to change the UID. Am I wrong?
If you hard-code the SerialVersionUID of a class, (to 1L, usually), store some instances, and then re-define the class, you basically get this behavior (which is more or less common sense):
New fields (present in class definition, not present in the serialized instance) are assigned a default value, which is null for objects, or the same value as an uninitialized field for primitives.
Removed fields (not present in class definition but present in the serialized instance) are simply ignored.
So the general rule of thumb is, if you simply add fields and methods, and don't change any of the existing stuff, AND if you're OK with default values for these new fields, you're generally OK.
Wow, a lot of bad information.
Java serialization is +very+ robust. There are a very well defined set of rules governing backwards compatibility of objects with the same uid and different data. the basic idea is that as long as you don't change the the type of an existing member, you can maintain the same uid without data issues.
that said, your code still needs to be smart about handling classes with potentially missing data. the object may deserialize correctly, but there may not be data in certain fields (e.g. if you added a field to the class and are deserializing an old version of the class). if your code can handle this, than you can probably keep the current uid. if not, then you should probably change it.
in addition to the pre-defined rules, there are advanced usage scenarios where you could even change the type of existing fields and still manage to deserialize the data, but that generally only necessary in extreme situations.
java serialization is very well documented online, you should be able to find all this information in the relevant sun/oracle tutorials/docs.
This only matters if you let Java generate a default UID for your class. It uses the actual members and methods of the class to generate it, thus making it invalid once you change the class structure. If you provide an UID for your class then this only matters if you need to deserialize older versions of your class from a file and such.
Want to define few point to highlight the changes which impacts serialization.
Below you will find the link to Oracle Java Docs for more details.
Incompatible Changes
Incompatible changes to classes are those changes for which the guarantee of interoperability cannot be maintained. The incompatible changes that may occur while evolving a class are:
Deleting fields
Moving classes up or down the hierarchy
Changing a nonstatic field to static or a nontransient field to transient
Changing the declared type of a primitive field
Changing the writeObject or readObject method so that it no longer writes or reads the default field data or changing it so that it attempts to write it or read it when the previous version did not.
Changing a class from Serializable to Externalizable or vice versa.
Changing a class from a non-enum type to an enum type or vice versa.
Removing either Serializable or Externalizable.
Adding the writeReplace or readResolve method to a class, if the behavior would produce an object that is incompatible with any older version of the class.
Link from where the above information is taken
http://docs.oracle.com/javase/7/docs/platform/serialization/spec/version.html#6678

Java: What is the fastest way to inject fields using reflection?

Suppose, I have a lot of classes, which are constructed using Java reflection (for some reason). Now I need to post-inject values to fields, which are
annotated with #PostInject.
public class SomeClass {
#PostInject
private final String someString = null;
public void someMethod() {
// here, someString has a value.
}
}
My question is: what is a fast way to set a field using reflection?
Remember, I need to do this very often on a lot of classes, that's
why performance is relevant.
What I would do by intuition is shown by this pseudo-code:
get all fields of the class
clazz.getFields();
check, which are annotated with #PostInject
eachField.getAnnotation(PostInject.class);
make these fields accessible
eachAnnotatedField.setAccessible(true);
set them to a certain value
eachAnnotatedField.set(clazz, someValue);
I'm afraid that getting all fields is the slowest thing to do.
Can I someone get a field, when I know it from the beginning?
NOTE: I can't just let the classes implement some interface, which would
allow to set the fields using a method. I need POJOs.
NOTE2: Why I want post-field injection: From the point of view of an API user, it must be possible to use final fields. Furthermore, when the types and number of fields are not known by the API a priori, it is impossible to achieve field initialization using an interface.
NOTE2b: From the point of view of the user, the final contract is not broken. It stays final. First, a field gets initialized, then it can't be changed. By the way: there are a lot of APIs which use this concept, one of them is JAXB (part of the JDK).
How about doing steps 1 to 3 just after you constructed the object and saving the set of annotated fields that you obtain either in the object itself or by keeping a separate map of class to set-of-annotated-fields?
Then, when you need to update the injected fields in an object, retrieve the set from either the object or the seperate map and perform step 4.
Don't know if it's any good, but this project looks like it would do what you want. Quote:
A set of reflection utilities and
miscellaneous utilities related to
working with classes and their fields
with no dependencies which is
compatible with java 1.5 and generics.
The utilities cache reflection data
for high performance operation but
uses weak/soft caching to avoid
holding open ClassLoaders and causing
the caches to exist in memory
permanently. The ability to override
the caching mechanism with your own is
supported.
Another option, as you say you know the few fields concerned from the beginning, is to ask only for those fields or methods.
Example : see getDeclaredMethod or getDeclaredField in java/lang/Class.html
You can exploit existing frameworks that allow to inject dependencies on object construction. For example Spring allows to do that with aspectj weaving. The general idea is that you define bean dependencies at spring level and just mark target classes in order to advise their object creation. Actual dependency resolution logic is injected directly to the class byte-code (it's possible to use either compile- or load-time weaving).
Fastest way to do anything with reflection is to cache the actual Reflection API classes whenever possible. For example I very recently made a yet-another-dynamic-POJO-manipulator which I believe is one of those things everyone ends up doing at some point which enables me to do this:
Object o = ...
BeanPropertyController c = BeanPropertyController.of(o);
for (String propertyName : c.getPropertyNames()) {
if (c.access(propertyName) == null &&
c.typeOf(propertyName).equals(String.class)) {
c.mutate(propertyName, "");
}
}
The way it works is that it basically has that one controller object which lazyloads all the properties of the bean (note: some magic involved) and then reuses them as long as the actual controller object is alive. All I can say is that by just saving the Method objects themselves I managed to turn that thing into a damn fast thing and I'm quite proud of it and even considering releasing it assuming I can manage to sort out copyrights etc.

Categories

Resources