Using Parcelable, Realm and GSON in Android development - java

It is okay to use Parcelable, Realm, and GSON in one project in Android development? I'm just wondering how to implement it simultaneously because each of these libraries/frameworks has different annotations when making a POJO. Another one is Realm and Parcelable both persist data, so do I need to implement both?

GSON used to have quirkiness with Realm and required the following config
Gson gson = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
#Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getDeclaringClass().equals(RealmObject.class);
}
#Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
})
.create();
GSON uses field reflection to read data from objects, which means that on managed RealmObjects, your fields will be null value.
This is because GSON also does not offer the option of using accessors to obtain the data, but Realm proxies do not copy the data to memory.
If you need an object that can be sent through Retrofit with #Body annotation and is a managed RealmObject, when you need to do apiService.sendObject(realm.copyFromRealm(myObject));.
Parcelable is not necessary for RealmObject in most cases, because any object that is managed by the Realm is already persisted, and readily available anywhere as long as you have its primary key.
But if you need to make detached modifiable copies of data and you're bent on using an unmanaged instance of the class directly to build the object you intend to save, then you can easily create Parcelable class using Parceler library.
In short:
RealmObjects are easily persistable to Parcelable using Parceler, but you typically don't need it, you just send the primary key between Activities and not the whole object
GSON doesn't work well with managed objects, because GSON is kinda dumb so you need to make an in-memory copy first
Personally, I prefer to keep my API response and my RealmModels separate, it's easier if you rely on mapping to a more optimal schema.

This should be no problem cause you can use multiple annotations to one method or one class.
If an annotation have the same name, you should give it the exactly package name like #java.lang.Override

Related

How to serialize session object in ARCore?

I use ARCore in a project and need to save the state from ARCore to use it at a later stage. The problem is that ARCore doesn't give any functions to set state. The idea then is to serialize the Session object and then deserialize it when needed.
I first tried to create a subclass of Session which implements Serializable, but that gave multiple NotSerializableException errors. Now I'm trying to solve this problem with Gson, using its ExclusionStrategy, to exclude the classes that aren't serializable. I'm not sure though how to approach this.
In MainActivity:
Gson gson = new GsonBuilder()
.addSerializationExclusionStrategy(new Strategy())
.create();
String jsonString = gson.toJson(session);
Strategy:
#Override
public boolean shouldSkipField(FieldAttributes field) {
return field.getDeclaredType().equals(** WHAT TO PUT HERE **.class);
}
#Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
I want the Session object serialized into a JSON object to be able to store it.
I don't think you'll be able to serialize your Session and recover it later. What you can do is store anchors informations to use it later. Services like AR Core Cloud Anchors and Azure Spatial Anchors can help you doing that.

Java serialization of non serializable third party class

I am currently developing a web application and I would like to make java objects persistent at the server so that they can be retrieved at any time. Since a database is an overkill for my application, I choose the easiest way of persisting java objects: serialization to xml or to bytes. Unfortunately a big part of the code I use are java classes which I cannot modify and these classes do not implement the interface 'serializable'. What are my options regarding to serializing objects of these classes, as well as other interacting objects of my own classes?
As I said in my comments, I'd go for a SerializationService which would find the proper Serializer<T> for every object you want to save.
Something like :
public interface Serializer<T> {
Serializable toSerializable(T objectToSerialize);
//to build a factory/service around it
boolean canDeserialize(Serializable serializedObject);
T fromSerializable(Serializable serializedObject);
}
And if you want a basic, concrete example : with the quite-common Path :
public class PathSerializer implements Serializer<Path> {
#Override
public Serializable toSerializable(Path objectToSerialize) {
return objectToSerialize.toString();
}
#Override
public Path fromSerializable(Serializable serializedObject) {
if(!canDeserialize(serializedObject)){
throw new IllegalArgumentException("Cannot deserialize this");
}
return Paths.get((String)serializedObject);
}
#Override
public boolean canDeserialize(Serializable serializedObject) {
return serializedObject != null && serializedObject instanceof String;
}
}
You could also very well store POJO containing the name your original object class and the list of parameters needed in its constructor an/or a map of its fields to be able to regenerate your objects by reflection.
It's all up to you and the complexity of your application.
I think JSON would be the go-to solution here. Take Googles GSON library for example. You don't need to annotate your classes, simply write
Gson gson = new Gson();
MyObj obj = gson.fromJson(jsonString);
String json = gson.toJson(obj);
For more general information about the JSON format see the official JSON documentation.
One option would be to extend the classes that you don't have access to, in order to save their internal state, and implement Serializable on those.
More info on this SO question:
Serializing a class variable which does not implement serializable
Besides this, I don't think there is any other option except building some wrappers and serializing the classes manually to XML or JSON.

How to JSON parse immutable object in Java + Jersey

So I am just trying out Jersey for REST services and it seems to we working out fine. I only expose get services and all of the object types that I expose with these services have an immutable object representation in Java. By default Jersey seems to use a parser (JAXB?), requiring a #XmlRootElement annotation for the class that should be parsed, zero-arg constructor and setters.
I have been using Gson with no zero-arg constructor, no setters and final on all fields with no problems at all. Is there any way to accomplish this with Jersey(i.e. the paser it is using)? I have seen solutions with adapter classes that map data from a immutable object to a mutable representation, but this seems like a lot of boilerplate(new classes, more annotations, etc.) if it can be achieved with Gson without anything added.
Note: 1) I have heard people promote using zero-arg constructor and claim that Gson should not work without it. This is not what I am interested in. 2) I really have tried googling this but my keywords might be off. In other words, humiliate me in moderation.
EDIT 1:
My webservice works if I do like this:
#XmlRootElement
public class Code{
private String code; //Silly object just used for example.
public Code(){}
//(G || S)etters
}
With this class exposing the object:
#GET
#Produces(MediaType.APPLICATION_JSON)
public Set<Code> get(#QueryParam("name") String name) { // Here I want to use a class of my own instead of String name, haven't figured out how yet.
return this.codeService.get(name);
}
If I replace the Code with the following, the webservice stops working:
public class Code{
private final String code;
#JsonCreator
public Code(#JsonProperty("code") String code) {
this.code = code;
}
//Getters omitted
}
What I want is to be able to 1) have immutable objects that can be parsed to/from json and 2) Be able to define something like #RequestBody in Spring MVC for my incoming objects.
Actually this could be pretty easy with Genson. You just need the jar and then configure the Genson feature to use constructors with arguments (if you don't want to put annotations on it).
Genson genson = new GensonBuilder().useConstructorWithArguments(true).create();
// and then register it with jersey
new ResourceConfig().register(new GensonJaxRSFeature().use(genson));
Or you can use JsonProperty on the arguments. See the User Guide for more details.

Order matters with class metadata in Genson - Is there a work-around?

I'm using Genson to serialize + deserialize json in my android app into polymorphic objects. The JSON is coming from a variety of sources though and I can't guarantee that the #class metadata will be the first line item in the json. Walking through the Genson code and writing test cases it looks like the #class metadata has to be the first entry in the dictionary.
Has anyone had luck working around this constraint? Is it time to switch to something else, and if so, what?
public class Message {
Payload payload;
// getters & setters
}
public abstract class Payload {
//
}
public class Notification1 extends Payload {
String text;
// getters & setters
}
public class Notification2 extends Payload {
String otherText
// getters & setters
}
String correctOrder = {"#class":"Message","payload":{"#class":"Notification1","text":"Text"}}
String modifiedOrder = {"#class":"Message","payload":{"text":"Text", "#class":"Notification1"}}
Genson g = Genson.Builder()
.addAlias("Notification1", Notification1.class)
.addAlias("Notification2", Notification2.class)
.useRuntimeType(true)
.useClassMetadata(true)
.useMetadata(true)
.useFields(false)
.useIndentation(false)
.create();
g.deserialize(correctOrder, Message.class) // This works
g.deserialize(modifiedOrder, Message.class) // This barfs with the error: com.owlike.genson.JsonBindingException: Could not deserialize to type class com.ol.communication.messages.Message
Indeed the order matters. This was choosed on purpose, see the remarks in the user guide.
If we allow the #class property anywhere in the json object, then we will have to first deserialize all the json object (and its sub properties obj/arr etc) to an intermediary data structure and then to the correct type.
This would incur additional memory overhead and less speed but greater flexibility, true.
A solution would be to mark classes that are polymorphic (annotation/config in the builder), for whom Genson would search/produce the #class property in the stream. This would allow to have this overhead only for the polymorphic objects in the stream.
At the moment it is not implemented, but I opened an issue. It will come in a future release.
Outside of the technical aspects, I don't think you should have polymorphic logic (or any other fancy stuff) when you are dealing with multiple external API. I mean this kind of features is library specific, so if you don't use the same tool on both sides you can run into troubles. Usually people have a layer that will be used to communicate with the APIs and map the data to YOUR model. If you don't own the code on both ends, I think this would be a good solution on the long term.

Patterns: Populate instance from Parameters and export it to XML

I'm building a simple RESTFul Service; and for achieve that I need two tasks:
Get an instance of my resource (i.e Book) from request parameters, so I can get that instance to be persisted
Build an XML document from that instance to send the representation to the clients
Right now, I'm doing both things in my POJO class:
public class Book implements Serializable {
private Long id;
public Book(Form form) {
//Initializing attributes
id = Long.parseLong(form.getFirstValue(Book.CODE_ELEMENT));
}
public Element toXml(Document document) {
// Getting an XML Representation of the Book
Element bookElement = document.createElement(BOOK_ELEMENT);
}
I've remembered an OO principle that said that behavior should be where the data is, but now my POJO depends from Request and XML API's and that doesn't feels right (also, that class has persistence anotations)
Is there any standard approach/pattern to solve that issue?
EDIT:
The libraries i'm using are Restlets and Objectify.
I agree with you when you say that the behavior should be where the data is. But at the same time, as you say I just don't feel confortable polluting a POJO interface with specific methods used for serialization means (which can grow considerably depending on the way you want to do it - JSON, XML, etc.).
1) Build an XML document from that instance to send the representation to the clients
In order to decouple the object from serialization logic, I would adopt the Strategy Pattern:
interface BookSerializerStrategy {
String serialize(Book book);
}
public class XmlBookSerializerStrategy implements BookSerializerStrategy {
public String serialize(Book book) {
// Do something to serialize your book.
}
}
public class JsonBookSerializerStrategy implements BookSerializerStrategy {
public String serialize(Book book) {
// Do something to serialize your book.
}
}
You POJO interface would become:
public class Book implements Serializable {
private Long id;
private BookSerializerStrategy serializer
public String serialize() {
return serializer.serialize(this);
}
public void setSerializer(BookSerializerStrategy serializer) {
this.serializer = serializer;
}
}
Using this approach you will be able to isolate the serialization logic in just one place and wouldn't pollute your POJO with that. Additionally, returning a String I won't need to couple you POJO with classes Document and Element.
2) Get an instance of my resource (i.e Book) from request parameters, so I can get that instance to be persisted
To find a pattern to handle the deserialization is more complex in my opinion. I really don't see a better way than to create a Factory with static methods in order to remove this logic from your POJO.
Another approach to answer your two questions would be something like JAXB uses: two different objects, an Unmarshaller in charge of deserialization and a Marshaller for serialization. Since Java 1.6, JAXB comes by default with JDK.
Finally, those are just suggestions. I've become really interested in your question actually and curious about other possible solutions.
Are you using Spring, or any other framework, in your project? If you used Spring, it would take care of serialization for you, as well as assigning request params to method params (parsing as needed).

Categories