Gwt serialization - java

I have a class Data which implements Serializable interface. This class has such fields
private boolean q = false;
private String a = "";
private List<Someclass> m = Collections.emptyList();
private List<Object[]> d = Collections.emptyList();
Values assigned to these members are default values. Class Someclass also implements Serializable and it has such columns
private Types sqlType;
private int columnWidth;
private String columnName;
Types is an enum which also implements serializable.
In Data class I have List<Object[]> d in which I will save data fethced from database through jdbc(when iterating ResultSet i use getObject() method). I use such construction, because it can run any query(query's structure is not known). In List<Someclass> m I hold metada of query. So when I try to fetch rows with simple query I get
com.google.gwt.user.client.rpc.SerializationException: Type '[Ljava.lang.Object;' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.: instance = [Ljava.lang.Object;#127053a9
Why it occures? All my transfer objects are serializable.
edit
Ok, Object is not Serializable so it can not be passed to and returned from the server. But what I should use in this case. Generics will not help me, because I don't know the type at compile time

In order for the class to be serializable, essentially everything you can get to from it has to also be serializable. In this case Object is not serializable, which makes Object[] not serializable, which makes List not serializable, which makes Data not serializable.
Think about it this way: If you can't serialize a given Object in the Object[], how are you going to serialize the Object[]? And if you can't serialize that, how are you going to serialize a list of that? And if you can't serialize that list, how are you going to serialize something that contains that list?
Now, it could be that everything in your Object[] ends up being serializable -- but the way you've typed it, the compiler can't guarantee that.
EDIT: Regarding what you should use instead, I would create some sort of wrapper class that will hold the SQL query's results, and make that one serializable.

You can't use List here because Object[] is not serializable.
You need to create a different, Serializable class that can hold any column value you get from your query.
Perhaps something like:
public abstract class ColumnValue implements Serializable
{
public abstract Object getValue();
}
public class IntColumnValue extends ColumnValue
{
private Integer _intValue;
public Object getValue()
{
return _intValue;
}
}
.
.
.
You create a sub-class of ColumnValue for each column type that might be returned. When you have an array of Object[], you move that to an array of ColumnValue[], choosing the correct sub-type for each value based on the meta-data from the query.

Related

Is There Any Memory-Efficient Java Equivalent to C unions or C++ std::variant?

I have a class Element<T> that contains a T and an int:
class Element<T>{
T obj;
int i;
// ...
}
When no T is stored, I would like to use obj like a pointer to an Element or an index:
obj = someElement;
obj = indexOf(someElement);
Of course, I can't do that because Java has no unions or variants (as in c++ variants) and has a strict type system.
Note that I would like to be able to access an Element through obj, but I have no desire to change it through obj, if that helps.
Questions:
Is there any way to accomplish this without creating my own variant
class or installing one?
If so, what is the most memory efficient way to do this, since I
will need to create many Elements?
The small problem is conceptual. An object in java is just some some memory on the heap, and its "address" which is stored in your object field.
class MyUnion {
Object any;
}
MyUnion u = new MyUnion();
u.any = "hello";
u.any = Integer.valueOf(13);
The construct above is a union of "addresses," not of data.
The closest to a union is a byte array, wrapped in a ByteBuffer.
ByteBuffer u = ByteBuffer.allocate(8);
u.putDouble(0, 3.14);
long x = u.getLong(0);
For real Object one must "serialize" them in some form:
String obj = "Ĉeĥoslovakio";
byte[] b = obj.getBytes(StandardCharsets.UTF_8);
u.putInt(b.length);
u.put(b);
For complex binary data one would use ASN or whatever other systematic technique.
So it is conceptual. You have no objects layouted on the stack (some JVMs do it sneakily), and: objects are indirect.
One way to approach this is by using an interface, or a super class with inheritance.
For example, if we had the following Java interface:
interface Element<T> {
T getValue();
}
then any class that implements the Element interface would need to provide a method that returned the value of an element.
We could implement a class that stored a T type object and returns it:
class ElementObject<T> implements Element<T> {
private T object;
T getValue() {
return object;
}
}
Or we could implement a class that stores an index and uses it (in conjunction with some big list of objects):
class ElementIndex<T> implements Element<T> {
private int index;
T getValue() {
return bigListOfObjects.get(index);
}
}
Now you could create a list or array or Elements and some of them could be ElementObjects and some could be ElementIndexs but they would both provide the access to an element as desired, without any wasted fields in either one.

Get Class Name for the given String

I have a use case, where I have stored the List of Java Data Types in DB, Like Byte, Character, Integer, Long, BigDecimal, BigInteger, Boolean.
So my use case is like If I read the value Long, I need to create the Long.class, if I read String, then String.class.
Class cls = Class.forName("java.lang.Long);, then I can use the cls for my own purpose.
I can achieve this, by having Enum of the above data types, as soon I read the value from the db, I pass the value to enum to get the class type. But I don't know whether it is efficient or not. Is there any method present in Java which gives like, for the given string,(without fully qualified name), it should return the class type.
Storing a reference to the Class object is efficient but using the Class object for reflection can be expensive. If you're just using the Class for reference then you're fine.
enum Decodable {
BIG_INTEGER(BigInteger.class),
INTEGER(Integer.class)
// etc
private final Class<?> decodableClass;
private Decodable(Class<?> decodableClass) {
this.decodableClass = decodableClass;
}
}
You could also just maintain a Set of Class objects.
private static final Set<Class<?>> DECODABLE_CLASSES = ImmutableSet.of(Integer.class, BigInteger.class); //etc

Save a list of objects to ORMLite database

I am looking for a way to save a list of objects to the database with ORMLite and read upon this question: Best way to store several ArrayLists in ORMLite for ApplicationSettings
And the accepted answer makes sense to me:
public class YourClass {
#GeneratedId
private int id;
#ForeignCollectionField
private Collection<MyString> bunchOfStrings = new ArrayList<MyString>();
}
public class MyString{
#DatabaseField(canBeNull = true, foreign = true)
private YourClass yourClass;
#DatabaseField
private String text;
}
And the only thing that I don't understand is this line private Collection<MyString> bunchOfStrings = new ArrayList<MyString>(). Why do we save the ForeignCollectionField as Collection<MyString> instead of as ArrayList<MyString>? When working with the bunchOfStrings object above, do we always need to cast it to ArrayList<MyString>?
Why do we save the ForeignCollectionField as Collection
instead of as ArrayList?
That was design consideration, excerpt from doc
The field type of orders must be either ForeignCollection<T> or Collection<T> – no other
collections are supported because they are much heavier with many methods to support
When working with the bunchOfStrings object above, do we always need
to cast it to ArrayList
You dont have to initialize that field, Ormlite will do that. Hence, only available methods are ones present in Collection or ForeignCollection

Add additional info to arraylist

What is the best way to store one single additional attribute at an arraylist?
Let's say I pass an ArrayList of Objects to a method and get an ArrayList back with an additional flag.
ArrayList<MyObject> list = new ArrayList<MyObject>();
//fill
list = myMethod(list);
And I want to get a boolean for each Object, but I don't want to store it directly in the object.
So data before myMethod: Apple, Banana, Grapefruit
After myMethod: Apple=>true, Banana=>false, Grapefruit=>false.
How can I store that additional attribute when not in the object? What is the best datatype? ArrayList can not do that, right?
You can create a custom wrapper around Object that has a field of type object and a boolean field. This is the best solution as you will be able to choose a meaningful name for the field.
Alternatively you can use the built-in class Pair and create a List<Pair<MyObject, Bool>>.
Use a class with a List<MyObject> field and a List<Boolean> field whose elements are flags parallel to every MyObject added in your List<MyObject>. Since this is too cumbersome, just add the boolean flag in MyObject. If you can't modify the class, extend it and add the boolean flag in your ExtendedMyObject extends MyObject class. If you can't extend it, make a wrapper class of MyObject that has a MyObject field and the boolean flag.
You could separately maintain a Set<MyObject> - membership in the Set would correspond to a true value for that object.
Assuming you used a HashSet, you would need to ensure MyObject implemented equals and hashCode. An alternative would be uniquely identifying each MyObject with a String, Long, etc. and maintaining a Set of those IDs.
I'd recommend just returning a Map with the source object (or name if unique) mapped to the boolean value.
Map<MyObject,Boolean> result = myMethod(list);
or, if name is unique:
Map<String,Boolean> result = myMethod(list);
for (MyObject item : list) {
Boolean result = result.get(item.getName());
if (result) {
...
}
}
If:
MyObject doesn't implement #hashCode (so you may get missed hashes for equal objects)
name isn't unique or
if result were more complex than a Boolean,
then I'd create a wrapper that wraps a MyObject with a result and return a List<MyObjectResult>.
Edit: BTW, I think you're right not to include the Boolean field on MyObject if it is not really a part of that object's state - i.e. if it's a transient result of some operation.
you can extend the ArrayList and give them a new property. For example:
public class MyArrayList<E> extends ArrayList<E>{
private boolean value;
public boolean isValue() {
return value;
}
public void setValue(boolean value) {
this.value = value;
}
}
there you can have all the features from the ArrayList and you have an additinal boolean field.
EDIT:
If your Boolean value has nothing to do with the Originalobject, why not just write a Wrapperclass? There are 2 possibilities to resolve this:
extend your Baseclass MyObject
Write a new class with 2 properties, one for the boolean and the other your instance of MyObject

How to serialize a list of type X, filled with objects of type Y, which extends X, and still get Y elements upon deserialization?

I have this list
LinkedList<ASD> list = new LinkedList<ASD>();
then, I add some objects which extend ASD
BSD bsd = new BSD(); // BSD extends ASD
list.add(bsd);
and serialize list.
How can I get it to serialize and deserialize teh bsd element as BSD and
not as ASD?
It is not a problem. All objects that you want to serialize must be instances of classes that implement Serializable. LinkedList does it. Declare either ASD or BSD (it does not matter in your case) to implement Serializable and try. Everything should work.
As noted by AlexR, everything is fine:
class ASD implements Serializable {
private static final long serialVersionUID = 1L;
}
class BSD extends ASD {
private static final long serialVersionUID = 1L;
}
LinkedList<ASD> list = new LinkedList<ASD>();
list.add(new BSD())
Now, if you serialize list, and later deserialize it, its elements will be of the correct type BSD.
Furthermore, the generic type argument (the <ASD> thing) is not saved during the serialization. The serialization procedure will only remember that list is a LinkedList object. What this means is that you can serialize an object of type LinkedList<ASD> and then deserialize it as LinkedList<BSD> (or even as e.g. LinkedList<Integer>). An exception can be thrown later, though, if you try to access an element of the list that cannot be cast to the newly specified generic type.
Finally, I'm just saying this is doable, not that it is a good practice :)

Categories