How to use a Serializable class - java

I'm using Backendless as a backend service, it offers a class called BackendlessUser for saving and retrieving users. I'm trying to pass a User between two activities on Android by passing it as Serializable extra:
Intent intent = new Intent(PeopleActivity.this, ConversationActivity.class);
intent.putExtra("withUser", contacts.get(position));
startActivity(intent);
Since the class BackendlessUser implements Serializable. However when I run it, it gives me this error:
java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.backendless.BackendlessUser)
at android.os.Parcel.writeSerializable(Parcel.java:1468)
at android.os.Parcel.writeValue(Parcel.java:1416)
....
Caused by: java.io.NotSerializableException: java.lang.Object
....
Due to, I think, this variable:
public final class BackendlessUser implements Serializable {
private final Map<String, Object> properties = new HashMap<String, Object>();
...
How can I solve this considering that I cannot modify the BackendlessUser class?

In Android you should use Parcelable which offers better performances compared to Serializable. For an explanation about how to implement it take a look at this answer
Also, if you need to use Parcelable on your map object, see this answer
Edit: since Object is not Parcelable though you might want to follow Alexander's answer, or, even better, use a database for data persistence

Instead of passing the object, you can save the reference to it in a singleton so that it's available between the activities.
You can extend the Application class and save there. The Application class exists all the time while your app is running and is a singleton.
public class MyApp extends Application {
public BackendUser currentUser;
}
Then:
((MyApp)getApplication()).currentUser

You should be using Parcelable to pass objects between activities. Parcelable is Android's version of Serializable, so you use that. You can find more information on Parcelable here.
If you can't modify the backend user, your best bet would be to use Alexanders suggestion and create a Singleton instance of User. This would allow you to create/update you user from any activity.

Related

Store 3rd party library object in database

Dear Stackoverflow community,
I'm developing a spring boot application which is using 3rd party library (https://github.com/goldmansachs/jdmn)
There is an object called TDefinitions which holds information about .dmn diagram.
Somehow I need to persist this object or all the information that this object contains in my database, using Spring Data JPA repository. So that I can reuse it whenever I run my application again.
Could you please assist me what would be the ways to achieve that? Store it as a Blob or maybe serialize it somehow as a Json?
The problem is it's not a simple object. Here's part of it's definition:
#JsonPropertyOrder({...})
public class TDefinitions extends TNamedElement implements Visitable {
#JsonProperty("import")
private List<TImport> _import;
private List<TItemDefinition> itemDefinition;
private List<TDRGElement> drgElement;
private List<TArtifact> artifact;
private List<TElementCollection> elementCollection;
private List<TBusinessContextElement> businessContextElement;
private DMNDI dmndi;
private String expressionLanguage;
private String typeLanguage;
[...]
How should I approach this problem from architectural perspective? How should I design my app? Provide interfaces/classes that extend elements from this library?
I'd prefer NoSQL such as MongoDB for storing these types of objects. If you have to use SQL for some reason, then go with JSON.

How to pass object one application to another application in android studio

I have two Android Application, where send object one application to another application.
when I share intent.putExtra("data", new CustomObject()) and also define in another application for received data intent.getSerializableExtra("data")
Getting error, when send data using custom object
Custom Class
Public class PatientObj implements Serializable {
public String getUserId() {
return UserId;
}
public void setUserId(String userId) {
UserId = userId;
}
public String getPatientId() {
return PatientId;
}
public void setPatientId(String patientId) {
PatientId = patientId;
}
public String getPatientName() {
return PatientName;
}
Getting Error
java.lang.RuntimeException: Parcelable encountered ClassNotFoundException reading a Serializable object (name = com.global.data.PatientObj)
at android.os.Parcel.readSerializable(Parcel.java:2952)
at android.os.Parcel.readValue(Parcel.java:2738)
at android.os.Parcel.readArrayMapInternal(Parcel.java:3054)
at android.os.BaseBundle.unparcel(BaseBundle.java:257)
at android.os.BaseBundle.getSerializable(BaseBundle.java:1162)
at android.os.Bundle.getSerializable(Bundle.java:982)
at android.content.Intent.getSerializableExtra(Intent.java:7261)
at com.app.android.ss_adv_type2.tevatronModule.connector.ProcessActivity.onCreate(ProcessActivity.java:40)
at android.app.Activity.performCreate(Activity.java:7383)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1218)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3256)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3411)
at android.app.ActivityThread.-wrap12(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1994)
at android.os.Handler.dispatchMessage(Handler.java:108)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7529)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
Caused by: java.lang.ClassNotFoundException: com.global.data.PatientObj
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:453)
at android.os.Parcel$2.resolveClass(Parcel.java:2938)
Paste the exact error you are facing, have you implemented Serializable Interface on CustomObject ?
This link help you
https://developer.android.com/training/sharing/receive
https://developer.android.com/guide/components/aidl.html
Can you share your error logs.
If your Custom Object implements the Serializable (or Parcelable) Interface, then you can bundle it in a Bundle that gets serialized or "bundled" in an Intent.
Keep in mind it's usually a potential code smell to pass something other than a primitive or two via intents. There are multiple reasons why this may be bad. Notice that it's may be bad, not it's bad. It really depends.
In general, on any mid-sized project, it's best if you plan to simply pass some ID or needed data so that the other activity (receiver) doesn't rely directly on your custom object, but rather fetches the data from a common "repository" or even Shared View Model if you don't have a repository "pattern" of any sort.
So instead of saying Here, Have this Custom Object, you merely say: Here's the ID of the data you need.
The other issues with passing stuff via intent is that you're by default serializing on the main thread (and deserializing). Additionally, if I correctly recall, there's a size limit (1mb?) for intents so if your CustomObject is bigger, you're going to have runtime issues and/or crashes.
You would avoid pretty much all these issues if you plan ahead to decouple this from the intent/activities.

Using callbacks to pass back data in a DialogFragment (android)

I have a DialogFragment that allows users to filter and search in the same Fragment. The filter works by passing back data to the hosting activity/fragment using a callback interface. This seemed to work great until I added a SearchView to the DialogFragment as when I enter text and click search it works but then throws the following expception and crashes:
Parcelable encountered IOException writing serializable object (name = com.braden.android.fragments.ListItemFragment$6)
...
Caused by: java.io.NotSerializableException: com.braden.android.fragments.ListItemFragment
To do the callback I used a fairly standard callback interface pattern. The interface extends Serializable. Here's the code for my callback:
private void displayFilter() {
FilterCategoryDialogFragment filterCategoryDialogFragment = new FilterCategoryDialogFragment();
Bundle bundle = new Bundle();
mOnFilterClickListener = new OnFilterClickListener() {
#Override
public void onCategoryClickListener(String filterName) {
updateVenues(mFilter);
}
};
bundle.putSerializable("listenerFilter",
mOnFilterClickListener);
filterCategoryDialogFragment.setArguments(bundle);
filterCategoryDialogFragment.show(getFragmentManager(), DIALOG_CATEGORY_FILTER);
}
This seems to have something to do with using an anonymous inner class that implements serializable so I'm wondering:
1) Why is it that I'm only receiving this exception when I use SearchView and not when I perform an action to send back data via callback or simply click out of the dialog.
2) Is there a workaround here or is this just a bad pattern for me to use.
I found the answer to this question here: Callback to a Fragment from a DialogFragment
They key is the "setTargetFragment" method which allows you to tell a fragment which fragment to send its result to. This allows you to avoid having to serialize an interface reference for the callback.
All fields of class must be Serialized, otherwise you should get NotSerializableException.
if you check Exception stack you will be able to find that object which not serialized.

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.

Register in android a session like value shared by all activity

How can I register data (like integer or poco objects) shared by all activity like the id of the user ? Have I to use a simple singleton or is there a special Android way ?
Note : I don't need to make that data persistant (no need of SharedPreferences or sqlite)
Thank you
You can create your own class that implements Application and specify this in your manifest file. In that case, every time you call getApplicationContext you will get a reference of your application that can hold any kind of information.
How to declare global variables in Android?
Sample code:
class MyApplication extends Application {
public void setMethod() {
//
}
}
((MyApplication)getApplicationContext()).setMethod()
The android way is to create a custom Application for your project. Then in onCreate of that application you initialize whatever you need, and for example from an Activity do something like:
((MyApplication) getApplication()).getMyData()
If using roboguice you can use a #Singleton injection which basically does the boilerplate of a singleton for you - that's much nicer.

Categories