Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java reflection handling library changes

Ok so I have an Android app and I started creating an addon system for the app so developers can code content providers that the app can then use to generate different content, I will not go through the whole procedure but everything works fine like so:

1) I created a library called com.myaddonlib that I imported in my project in this library there is an interface and different objects.

2) Now a developer can create a simple Java project on his end, import the library com.myaddonlib, and implement the interface on his main class which have methods that return different objects from the library.

3) Back on the android app, I can load the .jar file created by the developer (after the classes.dex is added to the jar file) and with the android DexClassLoader I can load the implemented interface like so :

DexClassLoader classloader = new DexClassLoader(jarFilePath, tempDirectory, null, context.getClass().getClassLoader());     
Class classToLoad = classloader.loadClass("com.apackage.Addon");

where Addon is the class created by the addon developer that implements the interface from the library residing in a package named com.apackage. I can then cast the interface from the library com.myaddonlib to a new instance of classToLoad and call the functions that the addon developer implemented.

Now here is the issue lets say I decided to update the addon library and remove one of the variables from a class, meaning that the addon's class is now different from the class in the updated library (used in the app). Even when the changed variable is not used something causes the app to crash without any error. Just the fact that both classes are different (even when the only difference is just a missing variable ) causes something to malfunction. Now this is not an easy procedure to explain so I would understand that given my bad english some have trouble following. My issue is that I need to know how to avoid this crash due to the change of the library on one of both ends. And also how java treats object changes in a situation like this

like image 503
Amro elaswar Avatar asked Apr 29 '17 01:04

Amro elaswar


People also ask

Why we should not use reflection in Java?

It's very bad because it ties your UI to your method names, which should be completely unrelated. Making an seemingly innocent change later on can have unexpected disastrous consequences. Using reflection is not a bad practice. Doing this sort of thing is a bad practice.

Does Java 11 support reflection?

Java 11 does not have API to dynamically augment the classpath at runtime but it can be done through reflection, with the obvious caveats about using internal API.

How does reflection help to manipulate Java code?

Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program. For example, it's possible for a Java class to obtain the names of all its members and display them.


1 Answers

My solution does not solve the problem, but instead makes sure it will never happen. The problem you are describing resembles the classic server-client problem. You have a server (in your case the app you are developing) and clients (the addons that are written by the developers). You can define an interface with many functions and pass data in binary structures. This would be more efficient from a traffic/parsing perspective, however whenever you change the API on the server you will have to update all the clients (or else crashes or other issues might occur).

So to solve this problem on the server-client many choose to use HTTP calls with JSON objects that describe the data. Although this way is less efficient, it allows adding APIs and supporting many client versions at the same time.

Using this approach in Android is quite simple. Define an API with two functions and a single interface:

public String sendDataToLibrary(String jsonString) {
   // Parse data, perform operation and return a JSON string as the result
}

public interface GetDataFromLibrary {
   String onDataFromLibrary(String jsonString);
}

public void init startLibrary(GetDataFromLibrary callback) {
   // Set callback in library and call it whenever you have data that needs to be sent out from the library asynchronously 
}

As you can see, if you implement this interface, you can pass any data around between the library and addons and it will never change so no crashes would occur. An improvement can be to force passing version number to allow the library to support multi-versioning).

like image 101
Doron Yakovlev Golani Avatar answered Oct 06 '22 00:10

Doron Yakovlev Golani