I have a Object Defined as
class MyObj {
int a;
String b;
Date d; //I will add the transient
}
During serialization the object was without 'transient' and the serialized string contains the Date. Now I am adding the 'transient' modifier with the Date. Will it be able to deserialize?
I have tested with my machine and it is working but somehow I am not confident on this one. I am using Gson for serialize/deserialize.
No.!
that is exactly the definition of transient keyword in java
Quote
transient is a Java keyword which marks a member variable not to be
serialized when it is persisted to streams of bytes.transient is a
Java keyword which marks a member variable not to be serialized when
it is persisted to streams of bytes.
Related
In a linked question I asked about a problem with Geode.Net client casting Geode PDX types to objects (domain objects) and this time I've a problem casting objects to Geode PDX types. It seems a region can hold both pdx serialized object types and other types of object and / or internal object types. By working with byte offsets I guess.
Anyway, this link shows a way to check for object types and handle them:
// get checks Object type and handles each appropriately
Object myObject = myRegion.get(myKey);
either as PDX instances or as domain object types:
if (myObject instanceof PdxInstance) {
// get returned PdxInstance instead of domain object
PdxInstance myPdxInstance = (PdxInstance)myObject;
then with GetField for a PDX Instance you can update just 1 field, very nice...
My problem is with domain objects:
else if (myObject instanceof DomainClass) {
// code to handle domain object instance
When coming from an event listener
public void AfterCreate(EntryEvent<TKey, TVal> ev)
I first of all try to cast ev.NewValue to Pdx or then the domain object and keep getting one of the following:
When the value in the region is a PdxInstance then without the if (myObject instanceof PdxInstance) as above to prevent it the cast IPdxInstance pdx = (IPdxInstance)ev.NewValue gives:
System.InvalidCastException: Unable to cast object of type myObject to type
Apache.Geode.Client.IPdxInstance
Which is to be expected. I seem to have broken the PdxSerialisation of myObject by creating the region <key, value> as <string, Object> even though myObject extends PdxSerializable and writing keys & values to the region is going through the ToData() override.
So then to deal with myObject directly for example myObject = ev.NewValue or myObject.Field1 = ((myObject)(ev.NewValue)).Field1 or like variations is giving:
Cannot implicitly convert type 'TVal' to 'myObject'
Cannot convert type 'TVal' to 'myObject'
Surely the event ev.NewValue to myObject cast ought to be straightforward so what am I missing? Otherwise I have to use ev.Key (which does cast without any exception) to specifically get the value again from the region in the cache by using:
IRegion<string, Object> r = cache.GetRegion<string, Object>(region);
return r[key];
So when the object is already given in the TVal type NewValue then why I just can't access it there? :-s
I recommend that you remove "read-serialized=true" and remove the type checking for IPdxInstance. You can still have PDX objects in your region without read-serialized=true. You really want the deserialized domain object itself in your callback and not the PDX instance. Turning off read-serialized will accomplish that and give you back your deserialized domain object in the AfterCreate method.
Note: The above recommendation is based on the fact that you are using a .NET client and .NET is giving you a compile error. This does not occur with Java clients. It's a bit puzzling why the .NET interaction is doing this.
FYI that it's well known that a region may contain either a PDX instance or a domain object in a region where PDX is being used. This is for performance efficiency. A primary node may store the domain object in a non-PDX form to avoid serialization costs but a PDX version on a secondary server. That is why clients always need to check the type before operating on the instance.
Yes, I understood that string was your key but it was whether or not you were using the Native Client that was my key question. The lower-case "s" was a clue.
Per programming your application to use PDX instances a region can hold either objects or PDX wrapped objects. For the former, casting through object is working. So I needed to write:
object o = ev.NewValue;
if (o.GetType().Name.Equals("PdxInstanceImpl"))
{
PdxInstance myPdx = (PdxInstance)o;
MyObject m = (MyObject)myPdx.GetObject();
string s = m.MyString;
decimal d = m.MyDecimal;
}
else
{
MyObject m = (MyObject)o;
string s = m.MyString;
decimal d = m.MyDecimal;
}
In JsonDeserialize annotation documentation the contentAs field is supposed to define the "Concrete type to deserialize content".
I tried to use this in combination, with either a Converter (via contentConverter field of the same annotation) or a JsonDeserializer (via contentUsing field of the same annotation), by extending either StdConverter or StdDeserializer, respectively, in an attempt to create an agnostic custom deserializer.
I cannot find a way to access the JsonDeserialize#contentAs information inside any of these two classes.
I am aware that the classes I extend from have a type parameter, I just put an Object class there. Documentation states
contentAs Concrete type to deserialize content (elements of a Collection/array, values of Maps) values as, instead of type otherwise declared. Must be a subtype of declared type; otherwise an exception may be thrown by deserializer.
Apparently I am applying the #JsonDeserializer annotation on a Collection of some persistable Class. I want to deserialize each such object, solely by knowing its id. Well, if I could only get that very type I defined in the #JsonDeserializer#contentAs field...
Can anyone tell me if this is possible anyhow?
I managed to implement the agnostic deserializer withou the use of #JsonDeserializer#contentAs after all.
After reading the javadocs of com.fasterxml.jackson.databind.JsonDeserializer I concluded that my custom deserializer should implement the com.fasterxml.jackson.databind.deser.ContextualDeserializer interface.
Inside the implementation of ContextualDeserializer#createContextual(DeserializationContext ctxt, BeanProperty property)
I could finally get access to the class type of the content of the collection, which I applied the #JsonDeserialize annotation on,
by calling:
ctxt.getContextualType().getRawClass()
NOTE that the same call inside the implementation of com.fasterxml.jackson.databind.JsonDeserializer#deserialize(com.fasterxml.jackson.core.JsonParser, com.fasterxml.jackson.databind.DeserializationContext) returned null, hence the need of the aforementioned interface.
All I had to do then is store the returned class in a member field (of type Class< ? >) of the custom deserializer and use it in the execution of JsonDeserializer#deserialize()
The only thing that remains to check is whether an instance of this custom deserializer is shared between threads. I only did some minor checks; I used the same implementation for two different collections of different types. I observed that ContextualDeserializer#createContextual(DeserializationContext ctxt, BeanProperty property) was called once (among multiple deserialization invokations), for each distinct type that was going to be deserialized. After checking during debugging, it seems that the same deserializer object is used for the same type. In my case, since what I store in the member field is this type itself, I don't mind if the same deserializer is used for the same java type to be deserialized because they should contain the same value. So we 're clear on this aspect as well.
EDIT: It appears all I have to do is update the com.fasterxml.jackson.databind.deser.std.StdDeserializer#_valueClass value to the now known class. Since it is final and since the ContextualDeserializer#createContextual(DeserializationContext ctxt, BeanProperty property) returns a JsonSerializer object, which is actually used,
instead of returning "this" serializer I can create a new one, passing the discovered class in the constructor, which actually sets the StdDeserializer#_valueClass to the class I actually want, and I'm all set!
Finally, NOTE that I didn't have to use the #JsonDeserializer#contentAs annotationfield as I get the value from the ctxt.getContextualType().getRawClass() statement inside ContextualDeserializer#createContextual(DeserializationContext ctxt, BeanProperty property) implementation
In an entity, I have an enumeration field which is translated in english and french.
In the same entity, I have a computed field that I am using as a toString, so I would like to build the computed field with the enumeration value translated in english or french, depending on the user's locale.
My question : in the getter of my computed field written in the extension of the entity, how could I get the user's locale and translate the enumeration value ?
You have to make your extension aware of its execution context. There are several interfaces that you can implement in your extensions so that they get injected with elements of their running context.
org.jspresso.framework.model.component.IComponentFactoryAware to receive an ICompoentFactory instance
org.jspresso.framework.security.ISubjectAware to receive the instance of the logged-in Subject
org.jspresso.framework.application.backend.session.IApplicationSessionAware to receive the current instance of IApplicationSession
org.jspresso.framework.model.entity.IEntityLifecycleHandlerAware to receive an instance of IEntityLifecycleHandler
In order to fulfill your use-case, the 4th interface must be implemented. Your extension will be injected with an instance of IEntityLifecycleHandler through the following method :
void setEntityLifecycleHandler(IEntityLifecycleHandler);
Just store this instance in your extension implementation as an instance parameter and use it afterwards in your code by safely casting it as a org.jspresso.framework.application.IController.
For instance :
public String getI18nLabel() {
String translationKey = "ENUM_NAME." + getComponent().getEnumValue();
IController controller = (IController) lifecycleHandler;
return controller.getTranslation(translationKey, controller.getLocale());
}
Just remember that the pattern for the I18N resource bundle key of enumerations is ${ENUM_NAME}.${ENUM_VALUE} which is computed as the translationKey local variable in the code above.
This question is merely out of interest and trying to understand something about memory management in object-oriented languages. It is not specific to one language, but I just want to understand as a general principle.
What I want to know is how the definition of an object reference is stored compared to the instance of that reference.
When you define and object in OO source code, e.g. in Java, without instantiating it:
String s;
How does this get stored? How does the memory usage of this definition differ from when the object is actually instantiated:
s = new String("abc");
? Is there a general principle that applies to all OO languages in terms of how memory is allocated or do different language implementers use different techniques for allocating memory?
Normaly when we declare a refrence like String s; it is created as a normal variable just like int , float but this type of variable hold the memory address ( it similar concept as pointers in C language) but when we use s = new String("abc");, it creates an object in heap and assign that address to the reference variable s.
In Java byte code, all Objects are stored as Objects. Explicit type-checking is added when needed. So for example this Java function
public Integer getValue(Object number){
int i = ((Number) number).toInt();
return new Integer(i);
}
is translated to a bytecode like this:
(accepts java.lang.Object, returns java.lang.Integer)
-read the first argument as an Object
-if the value is not a Number, raise an exception
-call the virtual method toInt(java.lang.Integer) of the value
and remember the int result
-use the value as an int argument
-instantiate a new java.lang.Integer
-call the constructor(int) of java.lang.Integer on the new number,
getting an Object back
[since the declared return value of Number.toInt is the same
as the return value of our function, no type checking is needed]
-return the value
So, types of unused variables get stripped out by the compiler. Types of public and protected fields are stored with its class.
The runtime type of an Object is stored with the object. In C++, it is a pointer to the Virtual Method Table. In Java, it is as a 16-bit index into the table of all loaded classes.
The Java class file stores an index of all dependent classes in a similar table. Only the class names are stored here. All field descriptions then point to this table.
So, when you write String s = new String("abc") (or even String s = "abc"), your class stores:
it is dependent on the class java.lang.String in the table of dependencies
"abc" in the table of String literals
your method loading a String literal by ID
(in the first case) your method calling a constructor of its first dependent class (String) with the first dependent class (String) as an argument.
the compiler can prove storing the new String in a String variable is safe, so it skips the type checking.
A class can be loaded as soon as it is referenced, or as late as its first use (in which case it is refered to by its depending class and ID within the class). I think the latter is always the case nowadays.
When a class is loaded:
-its class loader is asked to retreive the class by its name.
-(in the case of the system loader) the class loader looks
for the corresponding file in the program JAR, in the system library
and in all libraries referenced.
-the byte stream is then decoded into a structure in memory
-(in the case of early loading) all dependent classes are loaded recursively
if not already loaded
-it is stored in the class table
-(in the case of late loading) its static initialiser is run
(possibly loading more classes in the process).
In C++, none of the class loading takes place, as all user classes and most libraries are stored in the program as a mere virtual method table and the corresponding method. All of the system functions (not classes) can still be stored in a DLL (in case of Windows) or a similar file and loaded by the library at runtime. If a type checking is implied by an explicit type-cast, it is performed on the virtual method table. Also note that C++ did not have a type checking mechanism for a while.
I am reading JPA 2.0. I encounter a sentence that
We have used the transient modifier instead of the #Transient annotation so that
if the Employee gets serialized from one VM to another then the translated name
will get reinitialized to correspond to the locale of the new VM.
#Entity
public class Employee {
#Id private int id;
private String name;
private long salary;
transient private String translatedName;
// ...
public String toString() {
if (translatedName == null) {
translatedName = ResourceBundle.getBundle("EmpResources").getString("Employee");
}
return translatedName + ": " + id + " " + name;
}
}
What I understood is that when we use #Entity annotation and container encounter it then it call JPA provider that do the things. Like map id to ID column in database. Although we didn't mention the #Column annotation on the name and salary, but by default it maps to column NAME and SALARY in database. We used transient on translatedName so the JAP leave it as it is, not mapping applied to it. It's just a field in this class. But i am unable to get the understanding of the sentence
if the Employee gets serialized from one VM to another
Someone please explain it to me? Also tell me that what i defined above about the workflow of JAP is correct? Like what happening when container encounter #Entity annotation?
Thanks
When a class implements the java.io.Serializable interface, instances of this class are serializable. That means that the JVM can transform the object into a sequence of bytes. These bytes can be sent over the network, or saved on a disk, and can be read by another VM and transformed back into a Java object.
If a field has the transient Java keyword, it means that this field will be ignored by this serialization mechanism. The field won't be serialized.
A field annotated with #Transient is considered as a non-persistent field by JPA. It won't save it in the database, and it won't load it from the database. But it will be serialized if the object is sent to another JVM.
The Java transient keyword automatically makes a field #Transient. This means that a transient field, won't be serialized, and won't be saved by JPA either.
In the "JEE5 world" you can use detached entities as you would have used transfer objects. (I am not judging whether this is a good idea or not!)
Thus you can call for example a service method (e.g. EJB 3 SLSB method) that returns an instance of Employee remotely with the usual remote-call semantics regarding serialization.
It should be noted, that if an instance of Employee was serialized successfully, then your Java Runtime might be broken, as the class does not implement Serializable.
If you don't want to save the state of your entity arrtibute to DB and also don't want the state to get transferred to another jvm, then use Transient keyword.
If you don't want to save the state of your entity arrtibute to DB, but want the state to be transferred to another jvm, then use #Transient annotation.