Can a java object serialize itself? - java

I have a JPanel that handles a bunch of settings that I would like to save and load by file name.
It seems natural that since the panel already exists and knows all about itself that the load and save should be handled by the panel itself through a Save(String filename) and Load(String filename) actions attached to buttons.
However all the serialization and/or persistence examples I find require an external overseer that passes the object into the serializer functions.
Can I simply serialize the panel object using something similar to writeObject(this) and this=readObject() or is there a standard way to do this that I haven't searched properly for?

I am not sure I understand the question entirely but all the serialization logic definitely resides in the Object methods (readObject and writeObject).
When talking about who would invoke those methods, it all depends on your use case. There are several reasons for serializing an object, like for ex: if one wants to pass the object across the wire to another JVM, or you want to persist the state of the object between JVM restarts, or any other use case where the entire state of the Object needs to be saved outside of the JVM its running in.
In your use case, can it be done? yes. Is that a good practice, maybe not. An abstraction is better because what if you have a need to persist other objects not accessible to JPanel? What if there is a need perform some other logic before serializing an object? What if there is a need for ordering or some other requirement that cannot be handle by your JPanel?
You can learn more about Java Serialization here

Related

How do I replace Java's default deserialization with my own readObject call?

Someone thought it would be a good idea to store Objects in the database in a blob column using Java's default serialization methods.
The structure of these objects is controlled by another group and they changed a field type from BigDecimal to a Long,
but the data in our database remains the same.
Now we can't read the objects back because it causes ClassCastExceptions.
I tried to override it by writing my own readObject method,
but that throws a StreamCorruptedException because what was written by the default writeObject method.
How do I make my readObject call behave like Java's default one?
Is there a certain number of bytes I can skip to get to my data?
Externalizable allows you to take full control of serialization/deserialization. But it means you're responsible for writing and reading every field,
When it gets difficult though is when something was written out using the default serialization and you want to read it via Externalizable. (Or rather, it's impossible. If you try to read an object serialized with the default method using Externalizable, it'll just throw an exception.)
If you've got absolutely no control on the output, your only option is to keep two versions of the class: use the default deserialization of the old version, then convert to the new. The upside of this solution is that it keeps the "dirty" code in one place, separate from your nice and clean objects.
Again, unless you want to do things really complicated, your best option is to keep the old class as the "transport" bean and rename the class your code really uses to something else.
If you want to read what's already in your database your only option is to get them to change the class back again, and to institute some awareness that you're relying on the class definition as it was when the class was serialized. Merely implementing your own readObject() call can't fix this, and if the class is under someone else's control you can't do that anyway.
If you're prepared to throw away the existing data you have many other choices starting with custom Serialization, writeReplace()/readResolve(), Externalizable, ... or a different mechanism such as XML.
But if you're going to have third parties changing things whenever they feel like it you're always going to have problems of one kind or another.
BigDecimal to Long sounds like a retrograde step anyway.
Implement the readObject and readObjectNoData methods in you class.
Read the appropriate type using ObjectInoutStream.readObject and convert it to the new type
See the Serializable interface API for details.
More Details
You can only fix this easily if you control the source of the class that was serialized into the blob.
If you do not control this class,
then you have only a few limited and difficult options:
Have the controlling party give you a version of the class that reads the old format and writes the new format.
Write you own form of serialization (as in you read the blob and convert the bytes to classes) that can read the old format and generate new versions of the classes.
Write you own version of the class in question (remove the other from the class path) which reads the old format and produces some intermediate form (perhaps JSON).
Next you have to do one of these
Convince the powers that be that the blob technique is shitty and should be done away with. use the current class change as evidance. Almost any technique is better that this. Writing JSON to the db in the blob is better.
Stop depending on shitty classes from other people. (shitty is a judgement which I can only suspect, not know, is true). Instead create a suite of classes that represent the data in the database and convert from the externally controlled classes to the new data classes before writing to the database.

Where is the proper place to put code that saves objects to sharedpreference file

I guess this is a fairly generic object oriented question, but I am coming to the conclusion that I don't think enough in terms of objects.
I have two classes, a Person class and a People class. I will be reading and writing these (from and to the sharedPerferencesFile) from several activities. Right now I have a PersistData class that handles reading and writing. When I want to read or write these guys I get an instance of the PersistData class and then call methods like, persistData.write(person); or persistData.write(people);
Is this a good way to do this, or should I move the read and write code into the Person and People class?
I usually use a class i call settingsprovider, calling something like new SettingsProvider(this).getPerson(); and new SettingsProvider(this).setPerson(person); so yes, this is exactly how i would do it.
What you are doing looks to be correct. SharedPreference is a common file which is shared by all the components in the process. I mean all the classes in an application. So, your way of keeping PersistData and accessing it from person and people class looks clean and right approach.
As sharedPreference is a singlefile so the data will reamin persistant.
It depends on how you see / define the responsibilites of your classes. A Person does not necessarily need to know how to store it in shared preferences so something like Person#saveToPrefs() could be seen as bad design (tight coupling to shared preferences)
PersistData on the other hand does not need to know how the serialized format of a person looks in detail so that approach has it's weakness here.
I guess the cleanest way is to split the whole thing. A class that knows how to store stuff into shared preferences and a class that knows how to create serialized data of itself but does not care how that serialized data is used.

Storing custom java object inside Matlab Simulink block for a custom Toolbox

I'm working on building a custom Simulink block as a Matlab Toolbox. In order to avoid matlab's language to program the system, I'd like to make the system in Java as much as possible. I've researched the Matlab <-> Java interface, and it seems possible to do this. However, the one thing I couldn't find any information about was storing my custom Java object (holding the block's data) inside the Simulink block.
I conducted a quick test, and it seems storing a Java.lang.String instance is possible. However, that was a relatively simple test. Before jumping in head first, I wanted to check if this was even possible. Does anyone have experience with a similar setup? Does the object simply need to be Serializable to work?
For background information, I'm looking to implement the non-math part (GUI code, processing, etc) in Java. Math related elements would likely remain in matlab.
To store your Java object inside the block you should use its UserData block parameter. According to the documentation, you can put any data type in this parameter.
The only problems I can see with this are saving/loading and creation of new blocks. Saving/loading should be solved using serialization, but you will have to try it to see. If this doesn't work, then you could create a hidden mask parameter for your blocks, serialize your Java object to a string, and save the data in this mask during the PreSaveFcn callback. The data could be deserialized from the mask parameter in the LoadFcn callback.
For the creation of new blocks, you should set the PreCopyFcn callback of your library block and create your new Java object there. I have the feeling that if you don't do this, then MATLAB will copy the reference to your object from UserData (if one exists there already), which is probably not what you want.
You probably also want to override the OpenFcn callback since your aim is to use your Java object as a kind of souped-up mask, so that when a user double-clicks on the block you can show your custom UI.
For more information on block callback parameters, see this.

Best Practice (Design Pattern) for copying and augmenting Objects

I'm using an API providing access to a special server environment. This API has a wide range of Data objects you can retrieve from it. For Example APICar
Now I'd like to have "my own" data object (MyCar) containing all information of that data object but i'd like to either leave out some properties, augment it, or simply rename some of them.
This is because i need those data objects in a JSON driven client application. So when someone changes the API mentioned above and changes names of properties my client application will break immediatly.
My question is:
Is there a best practice or a design pattern to copy objects like this? Like when you have one Object and want to transfer it into another object of another class? I've seen something like that in eclipse called "AdapterFactory" and was wondering if it's wide used thing.
To make it more clear: I have ObjectA and i need ObjectB. ObjectA comes from the API and its class can change frequently. I need a method or an Object or a Class somewhere which is capable of turning an ObjectA into ObjectB.
I think you are looking for Design Pattern Adapter
It's really just wrapping an instance of class A in an instance of class B, to provide a different way of using it / different type.
"I think" because you mention copying issues, so it may not be as much a class/type thing as a persistence / transmission thing.
Depending on your situation you may also be interested in dynamic proxying, but that's a Java feature.

Make java methods visible to only specific classes

I have a manager class that is responsible for managing Objects of a certain kind. To do so it needs to manipulate these Objects, but these Objects have no relation to the manager whatsoever, so design technically, they are in separate packages "project.managers" and "project.objects" . The important thing is that the Objects in question should only be manipulated by the managers and nowhere else, but need to be accessible by every other class in the project.
As such I'd like to have the managers have access to manipulating methods, but restrict access to every other class. The most obvious one would be to move the manager class and object class into the same package and declare manipulating methods protected, but as the managers and objects are completely separate entities they don't fit there philosophically.
(This is partly because I want my IDE to stop showing me the manipulating methods whenever I autocomplete code on the Objects in question so I always have to go the route through the manager so corresponding tables are correctly updated whenever I change the Objects in question).
Are there any ideas to that or is the obvious way the best in any case?
Why not have an interface called
ManagerFunctions
and another called
ClientFunctions
You managed objects will implement both of these.
When you create the managed objects, you pass them around, but only as references to ClientFunctions. The manager objects will, however, refer to them as ManagerFunctions and consequently have access to their 'managed' functions. The appropriate casting will simply expose the appropriate methods.
Your IDE will automatically present you wil the appropriate methods depending on how these objects are referenced.
You're asking for something akin to the "friend" declarations of C++, but there's no direct equivalent in Java - package visibility is the nearest. Alternatively you could go for a model like the XML DOM, where the methods that should be public are defined in interfaces and all client access is via these interfaces. The manager would know the concrete class of the implementation so could downcast to that as required.
As such I'd like to have the managers have access to manipulating methods, but restrict access to every other class. The most obvious one would be to move the manager class and object class into the same package and declare manipulating methods protected...
Technically, you would declare the manipulating methods package protected (no modifier at all). Protected methods allow the class to be extended easier.
but as the managers and objects are completly seperate entities they don't fit there philosophically.
I understand. Java doesn't have the "friend" declaration that C++ has.
You could comment the manipulating methods, but that doesn't solve your Eclipse problem.

Categories