Java non-persistent but serializable variable - java

In java, how can I declare a variable which is not persistent to a database but it is serializable so that the variable is present in JSON representation of the object containing the variable?
I used the annotation #javax.persistence.Transient, but it doesn't work the way I want since #Transient variables are not serializable.

The issue may be solved by a specific workaround using modifiers. In order to avoid persisting fields, you have 4 options: marking the field with the modifier static, final or transient; or adding the #Transient annotation. Each of these will prevent the field from being persisted into the DB (see here).
Not all these limitations also apply to serialization though. Static and transient modifiers will prevent serialization, but final modifier will not - it will not be persisted but will be serialized (Deserializing in this case is a bit longer, but possible).
I hope this will be applicable to your issue.

Related

Java serialization and deserialization when the state of the class changes

How does serialization and deserialization work in the following cases:
When a new field is added to the class.
When a non static member is converted to static
When a non transient field becomes transient
When a transient field becomes non transient
In all of the cases described above, the java.io.InvalidClassException would be thrown in case you try to deserialize the class. The reason of this behaviour is that a serial version of the class used for deserialization does not match a serial version of the class used for class serialization. That is default behaviour.
This serial version of the class is used to verify that the serialized and deserialized objects have the same attributes and thus are compatible (which is not the case in your examples in the question).
If you don't explicitly declare a serialVersionUID field (of type long), the JVM will generate one automatically at run-time. However, if you're going to use Java serialization it is highly recommended to declare a serialVersionUID explicitly (because the generated one is compiler-dependent and thus may result in unexpected exceptions of java.io.InvalidClassException).
Suppose you explicitly declared serialVersionUID but you don't updated it during the changes. In your cases:
When a new field is added to the class. The object should de deserialized without any exceptions, a new field would have a default value.
When a non static member is converted to static. Your static field would have a value of corresponding non-static field.
When a non transient field becomes transient. Your transient field would be ignored during deserializtion and thus have a default value.
When a transient field becomes non transient. Because transient fields are ignored during serialization, this case is almost equal to the 1st case - your field would have a default value.

Why we need transient keyword to prevent serialization? [ Java ]

I do not understand that why we need transient keyword to prevent serialization of a particular data member. We can also make it static because static data member can not be serialized. Please guide me if I am wrong!
static does not just make a member not serialized; it also means that there is only one copy of that field for the entire class. If you want there to be a copy of that field for each object, but do not want that object to be serialized, you need transient; static will do something completely different.
Making variables static without fully understanding this is a massively common source of bugs for new Java developers.

which is the apt java keyword to skip java serialization

In a process of leaning java serialization concept, i was puzzled at one point. In java serialization process, we use 2 keywords to prevent serialization, i.e.., transient and static. If i don't want to save an instance variable, which keyword should i use, both does exactly the same.
Class A implements Serializable{
private static int x;
private transient int y;
private transient static int x;
}
In the above code all the three instance variables are not saved in a process of serialization. Which keyword is apt and recommended to prevent serialization. Why does two keywords have almost the same functionality. What is the recommended way of declaration to prevent serialization. Correct me if I'm wrong, I'm still learning.
The static keyword transforms an instance variable into a static variable. A side-effect is that the field is not serialized anymore... because it's not a field anymore.
A static variable is a variable of the class. An instance variable is a variable of the object, or instance of the class. You can't blindly go from one to the other.
Read the tutorial page about instance and static variables.
The transient keyword is the right keyword to use, of course.
You are confused: static fields are not instance variables, they are class-wide variables. By declaring a field static, the same field is shared among all instances of this class - it is not part of any specific object anymore, which leads to it not being serialized.
To specifically prevent serialization only transient is applicable...
Transient (and in JAXB XmlTransient) signify that the data is ephemeral and not of permanent importance and thus should just be ignored when it comes to matters of persistence.
Static means the value applies that the class level and thus serializing/deserializing it for multiple instances would be unsafe as values would collide.
Well, Let me define serialization once more.
A serialization is a process in which we persist state of an object.
So, is any static variable is part of an object's state ?..No absolutely not. It is the data which is shared among all objects of a class. So obviously, any static variable is not supposed to be serialized with object's state.
let's assume, we are allowed to persist an object's state. later on, if this variable is changed by some other object/class itself, and if we try to de-serialize the object then what value this static variable will hold. There will be a clash.
So if you want to prevent any instance variable from being serialized , do use transient.
when you will de-serialize the object it will be initialized with a default value.

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

A Question on Encapsulation

I know that encapsulation is binding the members and its behavior in one single entity. And it has made me think that the members have to be private. Does this mean if a class having public members is not following 100% Encapsulation rule?
Thanks
Encapsulation is both data bundling and data hiding. Java allows you to expose data, but you should have a very good reason for it if you choose to do so. Member variables should be made private as a default, and only promoted to higher visibility if absolutely necessary.
It means that internal fields (that you want to encapsulate in your class) should be private and only exposed via getter, setters, property's etc. Hiding and bundling the internal members of your class and controlling access through some method provided in your particular framework java (getters setters), .net (properties) etc is encapsulation.
And to answer your question why would you implement encapsulation? Well it so that you can control access to an internal member of you class. For instance if you had an integer field that you only wanted set to values in the range from 1 - 10. If you exposed the integer field directly there is no mechanism to keep a consumer from setting values outside your desired range. However, you can achieve this through encapsulation by exposing your internal int field though a setter or property thus allowing you to add validation code within the setter or property to "police" what values get set to your internal field.
Enjoy!
Correct. No data/state in the class should be exposed unless it's a final value.
Pretty much - if you think of an object as having state, now anybody can modify the state of your object without you knowing. At least with setter methods you can better control the state of the object.

Categories

Resources