Android classes and persistence - java

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.

Related

Can I achieve this using Serialization?

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.

Is Object deserialization a proper way to implement Prototype pattern in Java?

TL;DR
Can I use Java serialization/deserialization using Serializable interface, ObjectOutputStream and ObjectInputStream classes, and probably adding readObject and writeObject in the classes implementing Serializable as a valid implementation for Prototype pattern or not?
Note
This question is not to discuss if using copy constructor is better than serialization/deserialization or not.
I'm aware of the Prototype Pattern concept (from Wikipedia, emphasis mine):
The prototype pattern is a creational design pattern in software development. It is used when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects. This pattern is used to:
avoid subclasses of an object creator in the client application, like the abstract factory pattern does.
avoid the inherent cost of creating a new object in the standard way (e.g., using the 'new' keyword) when it is prohibitively expensive for a given application.
And from this Q/A: Examples of GoF Design Patterns in Java's core libraries, BalusC explains that prototype pattern in Java is implemented by Object#clone only if the class implements Cloneable interface (marker interface similar to Serializable to serialize/deserialize objects). The problem using this approach is noted in blog posts/related Q/As like these:
Copy Constructor versus Cloning
Java: recommended solution for deep cloning/copying an instance
So, another alternative is using a copy constructor to clone your objects (the DIY way), but this fails to implement the prototype pattern for the text I emphasized above:
avoid the inherent cost of creating a new object in the standard way (e.g., using the 'new' keyword)
AFAIK the only way to create an object without invoking its constructor is by deserialization, as noted in the example of the accepted answer of this question: How are constructors called during serialization and deserialization?
So, I'm just asking if using object deserialization through ObjectOutputStream (and knowing what you're doing, marking necessary fields as transient and understanding all the implications of this process) or a similar approach would be a proper implementation of Prototype Pattern.
Note: I don't think unmarshalling XML documents is a right implementation of this pattern because invokes the class constructor. Probably this also happens when unmarshalling JSON content as well.
People would advise using object constructor, and I would mind that option when working with simple objects. This question is more oriented to deep copying complex objects, where I may have 5 levels of objects to clone. For example:
//fields is an abbreviation for primitive type and String type fields
//that can vary between 1 and 20 (or more) declared fields in the class
//and all of them will be filled during application execution
class CustomerType {
//fields...
}
class Customer {
CustomerType customerType;
//fields
}
class Product {
//fields
}
class Order {
List<Product> productList;
Customer customer;
//fields
}
class InvoiceStatus {
//fields
}
class Invoice {
List<Order> orderList;
InvoiceStatus invoiceStatus;
//fields
}
//class to communicate invoice data for external systems
class InvoiceOutboundMessage {
List<Invoice> invoice;
//fields
}
Let's say, I want/need to copy a instance of InvoiceOutboundMessage. I don't think a copy constructor would apply in this case. IMO having a lot of copy constructors doesn't seem like a good design in this case.
Using Java object serialization directly is not quite the Prototype pattern, but serialization can be used to implement the pattern.
The Prototype pattern puts the responsibility of copying on the object to be copied. If you use serialization directly, the client needs to provide the deserialization and serialization code. If you own, or plan to write, all of the classes that are to be copied, it is easy to move the responsibility to those classes:
define a Prototype interface which extends Serializable and adds an instance method copy
define a concrete class PrototypeUtility with a static method copy that implements the serialization and deserialization in one place
define an abstract class AbstractPrototype that implements Prototype. Make its copy method delegate to PrototypeUtility.copy.
A class which needs to be a Prototype can either implement Prototype itself and use PrototypeUtility to do the work, or can just extend AbstractPrototype. By doing so it also advertises that it is safely Serializable.
If you don't own the classes whose instances are to be copied, you can't follow the Prototype pattern exactly, because you can't move the responsibility for copying to those classes. However, if those classes implement Serializable, you can still get the job done by using serialization directly.
Regarding copy constructors, those are a fine way to copy Java objects whose classes you know, but they don't meet the requirement that the Prototype pattern does that the client should not need to know the class of the object instance that it is copying. A client which doesn't know an instance's class but wants to use its copy constructor would have to use reflection to find a constructor whose only argument has the same class as the class it belongs to. That's ugly, and the client couldn't be sure that the constructor it found was a copy constructor. Implementing an interface addresses those issues cleanly.
Wikipedia's comment that the Prototype pattern avoids the cost of creating a new object seems misguided to me. (I see nothing about that in the Gang of Four description.) Wikipedia's example of an object that is expensive to create is an object which lists the occurrences of a word in a text, which of course are expensive to find. But it would be foolish to design your program so that the only way to get an instance of WordOccurrences was to actually analyze a text, especially if you then needed to copy that instance for some reason. Just give it a constructor with parameters that describe the entire state of the instance and assigns them to its fields, or a copy constructor.
So unless you're working with a third-party library that hides its reasonable constructors, forget about that performance canard. The important points of Prototype are that
it allows the client to copy an object instance without knowing its class, and
it accomplishes that goal without creating a hierarchy of factories, as meeting the same goal with the AbstractFactory pattern would.
I'm puzzled by this part of your requirements:
Note: I don't think unmarshalling XML documents is a right
implementation of this pattern because invokes the class constructor.
Probably this also happens when unmarshalling JSON content as well.
I understand that you might not want to implement a copy constructor, but you will always have a regular constructor. If this constructor is invoked by a library then what does it matter? Furthermore object creation in Java is cheap. I've used Jackson for marshalling/unmarshalling Java objects with great success. It is performant and has a number of awesome features that might be very helpful in your case. You could implement a deep copier as follows:
import com.fasterxml.jackson.databind.ObjectMapper;
public class MyCloner {
private ObjectMapper cloner; // with getter and setter
public <T> clone(T toClone){
String stringCopy = mapper.writeValueAsString(toClone);
T deepClone = mapper.readValue(stringCopy, toClone.getClass());
return deepClone;
}
}
Note that Jackson will work automatically with Beans (getter + setter pairs, no-arg constructor). For classes that break that pattern it needs additional configuration. One nice thing about this configuration is that it won't require you to edit your existing classes, so you can clone using JSON without any other part of your code knowing that JSON is being used.
Another reason I like this approach vs. serialization is it is more human debuggable (just look at the string to see what the data is). Additionally, there are tons of tools out there for working with JSON:
Online JSON formatter
Veiw JSON as HTML based webpage
Whereas tools for Java serialization isn't great.
One drawback to this approach is that by default duplicate references in the original object will be made unique in the copied object by default. Here is an example:
public class CloneTest {
public class MyObject { }
public class MyObjectContainer {
MyObject refA;
MyObject refB;
// Getters and Setters omitted
}
public static void runTest(){
MyCloner cloner = new MyCloner();
cloner.setCloner(new ObjectMapper());
MyObjectContainer container = new MyObjectContainer();
MyObject duplicateReference = new MyObject();
MyObjectContainer.setRefA(duplicateReference);
MyObjectContainer.setRefB(duplicateReference);
MyObjectContainer cloned = cloner.clone(container);
System.out.println(cloned.getRefA() == cloned.getRefB()); // Will print false
System.out.println(container.getRefA() == container.getRefB()); // Will print true
}
}
Given that there are several approaches to this problem each with their own pros and cons, I would claim there isn't a 'proper' way to implement the prototype pattern in Java. The right approach depends heavily on the environment you find yourself coding in. If you have constructors which do heavy computation (and can't circumvent them) then I suppose you don't have much option but to use Deserialization. Otherwise, I would prefer the JSON/XML approach. If external libraries weren't allowed and I could modify my beans, then I'd use Dave's approach.
Your question is really interesting Luiggi (I voted for it because the idea is great), it's a pitty you don't say what you are really concerned about. So I'll try to answer what I know and let you choose what you find arguable:
Advantages :
In terms of memory use, you will get a very good memory consumption by using serialization since it serializes your objects in binary format (and not in text as json or worse: xml). You may have to choose a strategy to keep your objects "pattern" in memory as long as you need it, and persist it in a "less used first persisted" strategy, or "first used first persisted"
Coding it is pretty direct. There are some rules to respect, but it you don't have many complex structures, this remains maintainable
No need for external libraries, this is pretty an advantage in institutions with strict security/legal rules (validations for each library to be used in a program)
If you don't need to maintain your objects between versions of the program/ versions of the JVM. You can profit from each JVM update as speed is a real concern for java programs, and it's very related to io operations (JMX, memory read/writes, nio, etc...). So there are big chances that new versions will have optimized io/memory usage/serialization algos and you will find you're writing/reading faster with no code change.
Disadvantages :
You loose all your prototypes if you change any object in the tree. Serialization works only with the same object definition
You need to deserialize an object to see what is inside it: as opposed to the prototype pattern that is 'self documenting' if you take it from a Spring / Guice configuration file. The binary objects saved to disk are pretty opaque
If you're planning to do a reusable library, you're imposing to your library users a pretty strict pattern (implementing Serializable on each object, or using transient for dields that are not serializable). In addition this constraints cannot be checked by the compiler, you have to run the program to see if there's something wrong (which might not be visible immediately if an object in the tree is null for the tests). Naturally, I'm comparing it to other prototyping technologies (Guice for example had the main feature of being compile time checked, Spring did it lately too)
I think it's all what comes to my mind for now, I'll add a comment if any new aspect raises suddenly :)
Naturally I don't know how fast is writing an object as bytes compared to invoking a constructor. The answer to this should be mass write/read tests
But the question is worth thinking.
There are cases where creating new object using copy constructor is different from creating new object "in a standard way". One example is explained in the Wikipedia link in your question. In that example, to create new WordOccurrences using the constructor WordOccurrences(text, word), we need to perform heavyweight computation. If we use copy constructor WordOccurrences(wordOccurences) instead, we can immediately get the result of that computation (in the Wikipedia, clone method is used, but the principle is the same).

Java serialization: static variables not serializable: workaround

Ok, so this question is mostly just related to: is there a better way to do this?
I have a phonebook application, and you can add users to it, delete them, and such, with each person being assigned a distinct ID#. A Person class stores lastIDused as a static class variable. The phonebook class has a vector of Persons.
My workaround thought is this: create a new non-static variable for the Person class, and upon serializing/saving, for the 1st element in the vector only, store the static variable's data into this new variable. Then, when de-serializing, re-set the static variable using the 1st Person's such-variable.
Going back to my original question: is there a better/more-formal/proper way to do this?
A better solution (IMO) would be to make lastIdUsed an instance field of the PhoneBook class. It sounds like you are already serializing an instance of that class ...
FWIW - making lastIdUsed an instance field of Person is just bad object modelling. The field is almost never going to be useful and almost never going to have a valid value. It will only have a valid value in the case of the first serialized Person in a PhoneBook.
First, I would avoid this kind of thing entirely. Static variables aren't serializable for a reason, namely by deserializing something you would invalidate the state of other objects. For example, if your lastUsedId is at 10 and you deserialize an object where it was at 5, it could lead to creating duplicates (6-10).
However, if you are still going to do this, check out the Externalizable interface. It lets you control the serialization and deserialization of an object. Here[1] is a good discussion on it. In the past I've used Externalizable to more tightly control the format of the object being serialized in order to save space. If you really want to, you could serialize a static variable and set it when you deserialize. You could even only set it if it is higher than the value currently in memory. Again, like other commenters I would advise against this approach entirely, but it doesn't hurt to learn this stuff, eh?
[1] What is the difference between Serializable and Externalizable in Java?

force serialization of static fields

I need to persist several classes with A LOT of static fields (which are arrays filled & modified during the runtime). It would take a lot of effort to convert from static fields to instance vars, so I'd rather go for a quick solution, if any.
So far the path of least resistance is to cook my own writeObject() for each class.
Alternatively, i dont need Serialization as such - any mechanism to store/load an object from persistent storage will do. E.g. XMLDecoder to decompose the bean objects, etc.
You could write a method to use reflection to serialize all static methods. A static method can be marked transient which would normally be redundant, but you could use this to highlight static fields you don't want to serialize. You can call this method from your writeObject() to save you having to do this for every field.
I'd create a new class that gathers all those static fields, lets call it StaticInfoClass. In StaticInfoClass create all the fields non-static. Create a property in the old class that is type of StaticInfoClass. All instances of the your original class will hold a reference to a unique instance of StaticInfoClass, that will contain all the arrays filled and modified during the runtime. If you have threads make sure you make it a bean with synchronized methods to avoid race conditions.
With this approach, in essence, you are implementing static fields without actually using the static modifier. This simple approach should easy a lot your serialization and deserialization problems and most frameworks will handle it very easily.
Also remember that static fields and global state in programs are normally a bad practice, it should be avoided. I tend to not use static if it is not to declare constants or other trivial data structures that definitely do not changed in runtime.
Have not tried this but might work. if your class defines an array of ObjectStreamField objects named serialPersistentFields , then you can explicitly declare the specific fields saved. You can shove any value into it, even the static fields.
private static String lastUser;
private static int maxAge;
private final static ObjectStreamField[]
serialPersistentFields = {
new ObjectStreamField(
"lastUser", String.class),
new ObjectStreamField("maxAge", int.class)
};
Then you will have to implement readObject, to fetch these values and set it for your static variables. So basically this mechanism allows you to marshall/unmarshall fields from anywhere via serialization. You just need to know what to do with them once you read them back. I would still recommend paying the price for moving your statics to member variables.
details : http://java.sun.com/developer/technicalArticles/ALT/serialization/

Java create dynamic class

I have 2 questions that I was hoping someone could help me with. Is there a way to create a class on the fly with android/java and also add variables to the class? For example I would like to do something like this:
Class c = new Class();
c.name = 'testing';
c.count = 0;
c.getName = new function(){
return c.name;
}
Just wondering if this is possible or if there is another way to do this. Basically I want to build an object that I can use the data from as an object.
No, the syntax you describe is not possible in Java. I'm not sure what you are trying to accomplish there. If you want to create a class to use to hold data on the fly, you can create an anoynmous inner class.
Object object = new Object() {
private String name = testing;
private int count = 0;
public String getName() {
return name;
}
}
In general, I wouldn't use this for a data objects though. This functionality is typically used for anonymous implementations of interfaces to support callbacks, etc.
This is not typically done. It can be done by reflection, but would be a fairly bad idea--This type of code is really annoying to debug, won't interact correctly in the IDE (For instance, ctrl-clicking on an instance of c.getName wouldn't be able to jump to where the method is defined), it would probably be a pretty big performance hit, etc.
However, for some generic tools this is possible. I believe Hibernate might have the ability to create classes from DB tables.
The most common use, however, is in mocking used within testing frameworks--They can do almost exactly what you want. Look at EasyMock with TestNG.
In general, though, you are better off just defining a business class and going with it rather than trying to make some abstract framework that generates your classes for you.

Categories

Resources