Composition over inheritance for RealmObjects with Gson serialization - java

I'm considering Realm as a database solution for various reasons, but the big one currently being the TransactionTooLargeException now being thrown in Nougat has made it so I have to rework my current database architecture, based on ActiveAndroid, which has its own annoying limitations. The difficulty is that Realm does not support inheritance (https://github.com/realm/realm-java/issues/761) and they don't seem in any particular hurry to get around to it. Instead, they recommend using composition over inheritance, but I can't figure out how to make that work with Gson/Json deserialization.
Example:
Superclass: Animal, with subclasses Dog and German Shepherd
public class Animal {
private int numLegs;
private boolean hasFur;
}
public class Dog extends Animal {
private String color;
private boolean canDoTricks;
}
public class GermanShepherd extends Dog {
public boolean isGuardDog;
public boolean isAtRiskOfHipDysplasia()
}
(Sorry, this is a super canned example, just to illustrate).
Now let's say the json for this looks like:
{
"numLegs" : 4,
"hasFur" : true,
"color" : "Black & Brown",
"canDoTricks" : true,
"isGuardDog" : true,
"isAtRiskofHipDysplasia" : false
}
Now, I cannot modify the Json because it's an API that's giving it to me.
Looking at this answer: https://stackoverflow.com/a/41552457/4560689, it appears it is possible in a very hacky way to make it sort of work, but the answer notes that there are limitations including that the serialization would be wrong. Since the server only talks in the json format that doesn't involve crazy composition, this presents a problem.
Can I write a custom Gson deserializer/serializer to make this work? If so, what would that look like? I basically need to be able to convert a json payload into up to N objects, where N - 1 objects are nested inside the base object.
So with composition (note this isn't necessarily "Realm" composition, just an example, since it looks like Realm has to use some weird form of interface-composition), I'd have a class like below:
public class GermanShepherd {
public Animal animal;
public Dog dog;
// Generate a bunch of delegate methods here
}
Am I barking up the wrong tree? It feels like Realm might not work for what I'm trying to do, and inheritance is built into the API I'm using in multiple places, and specifically in the objects I want to persist, so I have to either figure out a workaround or use another solution. ActiveAndroid (what I'm using now) is also a less than ideal solution and I'm sick to death of dealing with skirting around deadlocks, crashes, querying on background threads that now cause crashes if the data is too big to pass in an Intent, etc...all issues with SQLite. I'm open to solutions to my main question or to alternatives that would solve this problem. Thanks in advance for your help!

You should create a new RealmObject class for each flattened concrete class, and map your JSON representation to them.
To retain inheritance, you can simulate it by inheriting getters/setters from interfaces that inherit from one another.
public interface IAnimal extends RealmModel {
int getNumberOfLegs();
void setNumberOfLegs(int legs);
boolean getHasFur();
void setHasFur(boolean hasFur);
}
public interface IDog extends IAnimal {
String getColor();
void setColor(String color);
boolean getCanDoTricks();
void setCanDoTricks();
}
public interface IGermanShepherd extends IDog {
boolean getIsGuardDog();
void setIsGuardDog(boolean isGuardDog);
boolean getIsAtRiskOfHipDysplasia();
void setIsAtRiskOfHipDysplasia(boolean isAtRisk);
}
Because then you can do
public class GermanShepard
extends RealmObject
implements IGermanShepard {
private int numLegs;
private boolean hasFur;
private String color;
private boolean canDoTricks;
private boolean isGuardDog;
private boolean isAtRiskofHipDysplasia;
// inherited getters/setters
}
You can even make repository class out of it
public abstract class AnimalRepository<T extends IAnimal> {
protected Class<T> clazz;
public AnimalRepository(Class<T> clazz) {
this.clazz = clazz;
}
public RealmResults<T> findAll(Realm realm) {
return realm.where(clazz).findAll();
}
}
#Singleton
public class GermanShepardRepository extends AnimalRepository<GermanShepard> {
#Inject
public GermanShepardRepository() {
super(GermanShepard.class);
}
}
And then
#Inject
GermanShepardRepository germanShepardRepository;
RealmResults<GermanShepard> results = germanShepardRepository.findAll(realm);
But you can indeed merge them into one class and then give it a String type; parameter to know what type it originally was. That's probably even better than having all these GermanShepards.

Related

Implementing a generic container for a list of interface instances in Java

Java 8 here. I have the following POJOs:
public interface HasPartNumber {
String getPartNumber();
}
#Getter
#Setter
public class InventoryItem implements HasPartNumber {
private String modelNumber;
private String description;
// lots of other fields here
#Override
public String getPartNumber() {
return this.modelNumber;
}
}
public class Inventory extends ArrayList<InventoryItem> {
// Inventory is just an alias of a list of InventoryItem
}
#Getter
#Setter
public class PriceItem implements HasPartNumber {
private String equipmentNumber;
// lots of other fields here
#Override
public String getPartNumber() {
return this.equipmentNumber;
}
}
public class PriceRoster extends ArrayList<PriceItem> {
// PriceRoster is just an alias of a list of PriceItem
}
I understand some of you may have an aversion to how I'm modeling Inventory and PriceRoster, but using the is-a and has-a golden rule, it is correct. An "inventory" is no more and no less than just a list of InventoryItems. Ditto for PriceRoster. And, the Domain-Driven Design community would probably agree that these are valid data models if it makes sense to a developer reading the code.
However, I am not married to this design. And so while my druthers would be to keep this data model above, if it truly is impossible to accomplish what I describe below without changing the data model, I'll be flexible.
I am trying to write a generic PartProcessor class that will iterate through lists of HasPartNumber impls and perform processing on them. My best attempt:
public class PartProcessor<PART_CONTAINER extends List<HasPartNumber>> {
public void process(PART_CONTAINER partContainer) {
partContainer.stream().forEach(part -> {
// Do something here
});
}
}
produces compilation errors when I go to instantiate the PartProcessor:
PartProcessor<Inventory> inventory = new PartProcessor<Inventory>();
The compiler errors I'm seeing are:
"Type parameter 'com.example.myapp.Inventory' is not within its bound; should implement 'java.util.List<com.example.myapp.HasPartNumber>'"
Any ideas what I can do to get my PartProcessor working generically on any list of HasPartNumbers impl, including Inventory and PriceRoster?
bounded types makes the type covariant:
public class PartProcessor<PART_CONTAINER extends List<? extends HasPartNumber>> {...
For a broader read see this answer also.

Java generics in List return type on a method inherited from multiple interfaces

I'm currently working at a company that has a diverse set of modules. In that company if you want to provide module internals you provide it via a java interface, that hides the actual implementing type and gives an interface for the requesting module. Now I want to have one provider to be able to provide data for multiple modules that expose different fields or methods of the actual internal data.
Therefore I have an internal Object, which has some data and I have an interface for each module that needs access to some but not strictly all fields. Finally I have an external object that implements all those interfaces and holds an instance of the internal object to delegate the method calls:
public class InternalObject {
public int getA() { return 0; }
public int getB() { return 0; }
}
public interface ModuleXObject {
int getA();
}
public interface ModuleYObject {
int getA();
int getB();
}
public class ExternalObject implements ModuleXObject, ModuleYObject {
private InternalObject _internal;
public int getA() { return _internal.getA(); }
public int getB() { return _internal.getB(); }
}
Now that is all fine and dandy, but if I want to provide - lets say - repository methods for finding a list of said objects typed for the correct module, I run into problems with how I can achieve that. I would wish for something like the following:
public interface ModuleXObjectRepository {
List<ModuleXObject> loadAllObjects();
}
public interface ModuleYObjectRepository {
List<ModuleYObject> loadAllObjects();
}
public class ExternalObjectRepository implements ModuleXObjectRepository, ModuleYObjectRepository {
public List<ExternalObject> loadAllObjects() {
// ...
}
}
This doesn't compile saying the return type is incompatible.
So my question is, if it is possible to achieve something like that and if, how?
I should note that I tried some different approaches which I want to include for completeness and to portray their downsides (in my eyes).
Approach 1:
public interface ModuleXObjectRepository {
List<? extends ModuleXObject> loadAllObjects();
}
public interface ModuleYObjectRepository {
List<? extends ModuleYObject> loadAllObjects();
}
public class ExternalObjectRepository implements ModuleXObjectRepository, ModuleYObjectRepository {
public List<ExternalObject> loadAllObjects() {
// ...
}
}
This approach is quite close to the solution I would prefer, but results in code like this:
List<? extends ModuleXObject> objects = repository.loadAllObjects();
Therefore requiring the user to include the "? extends" into each List-Declaration regarding to an invocation of loadAllObjects().
Approach 2:
public interface ModuleXObjectRepository {
List<ModuleXObject> loadAllObjects();
}
public interface ModuleYObjectRepository {
List<ModuleYObject> loadAllObjects();
}
public class ExternalObjectRepository implements ModuleXObjectRepository, ModuleYObjectRepository {
public List loadAllObjects() {
// ...
}
}
This approach just omits the generic in the ExternalObjectRepository and therefore reduces the type safety too much in my opinion. Also I haven't tested if this actually works.
Just to reharse, is there any possible way to define the loadAllObjects-method in a way that enables users to get lists that are typed with the objects for their respective module without
requiring "? extends" in the users code
degrading type safety in the repository implementation
using class/interface level generics
The challenge with allowing it to be typed as List<ModuleXObject> is that other code may hold is as a List<ExternalObject>.
All ExternalObject instances are ModuleXObject instances but the inverse is not true.
Consider the following additional class:
public class MonkeyWrench implements ModuleXObject{
//STUFF
}
MonkeyWrench instances are NOT ExternalObject instances but if one could cast a List<ExternalObject> to a List<ModuleXObject> one could add MonkeyWrench instances to this collection, and this causes a risk of run time class cast exceptions and ruins type safety.
Other code could very easily have:
for(ExternalObject externalObject:externalObjectRepository.loadAllObjects())
If one of those instances is a MonkeyWrench instance, run time class cast, which is what generics are meant to avoid.
The implication of ? extends ModuleXObject is that you can read any object from the collection as a ModuleXObject but you can't add anything to the collection as other code may have additional constraints on the collection that are not obvious/available at compile time.
I'd suggest in your case to use ? extends ModuleXObject as its semantics seem to align with what you want, namely pulling out ModuleXObject instances, e.g.
ModuleXObjectRepository repo = //get repo however
for(ModuleXObject obj : repo.loadAllObjects()){
//do stuff with obj
}

Varying enums in Java being accessed by common method

Essentially what I'm trying to do is create a generic method that can take many different kinds of enums. I'm looking for a way to do it how I'm going to describe, or any other way a person might think of.
I've got a base class, and many other classes extend off that. In each of those classes, I want to have an enum called Includes like this:
public enum Includes {
VENDOR ("Vendor"),
OFFERS_CODES ("OffersCodes"),
REMAINING_REDEMPTIONS ("RemainingRedemptions");
private String urlParam;
Includes(String urlParam) {
this.urlParam = urlParam;
}
public String getUrlParam() {
return urlParam;
}
}
I've got a method that takes in a generic class that extends from BaseClass, and I want to be able to also pass any of the includes on that class to the method, and be able to access the methods on the enum, like this:
ApiHelper.Response<Offer> offer = apiHelper.post(new Offer(), Offer.Includes.VENDOR);
public <T extends BaseClass> Response<T> post(T inputObject, Includes... includes) {
ArrayList<String> urlParams = new ArrayList<String>();
for (Include include : includes){
urlParams.add(include.getUrlParam());
}
return null;
}
Is there a way to be able to pass in all the different kinds of enums, or is there a better way to do this?
---EDIT---
I've added an interface to my enum, but how can I generify my method? I've got this:
public <T extends BaseClass> Response<T> post(Offer inputObject, BaseClass.Includes includes) {
for (Enum include : includes){
if (include instanceof Offer.Includes){
((Offer.Includes) include).getUrlParam();
}
}
return null;
}
But I get an error on apiHelper.post(new Offer(), Offer.Includes.VENDOR); saying the second param must be BaseClass.Includes.
Enums can implement interfaces, so you can create an interface with these methods that you'd like to be able to call:
interface SomeBaseClass {
String getUrlParam();
void setUrlParam(String urlParam);
}
and then your enum can implement this interface:
public enum Includes implements SomeBaseClass {
VENDOR ("Vendor"),
OFFERS_CODES ("OffersCodes"),
REMAINING_REDEMPTIONS ("RemainingRedemptions");
private String urlParam;
Includes(String urlParam) {
this.urlParam = urlParam;
}
#Override
public String getUrlParam() {
return urlParam;
}
#Override
public void setUrlParam(String urlParam) {
this.urlParam = urlParam;
}
}
If you want to get really fancy, it's possible to restrict subtypes of the interface to enums, but the generic type declaration will be pretty ugly (thus hard to understand and maintain) and probably won't provide any "real" benefits.
Unrelated note regarding this design: it's a pretty strong code smell that the enum instances are mutable. Reconsider why you need that setUrlParam() method in the first place.

Code repetition vs readablility

I have multiple services (in Spring MVC) that are children of a global Service. So I need to know about the best practice (or your opinions) with multiple methods with this example:
//Domain classes
public class MyParentObject{}
public class MyObj extends MyParentObject{}
//Services
public class MyParentObjectServiceImpl implements MyParentObjectService{
#Override
public MyParentObject findObjectByProp(String prop, String objectType){
//myCode (not abstract class)
}
}
public class MyObjServiceImpl extends MyParentObjectServiceImpl implements MyObjectService{
private myObjType = "MyObj";
#Override
public MyObj findMyObjByProp(String prop){
return (MyObj) super.findObjectByProp(prop, this.myObjType);
}
}
And in this approach, I use calls like this:
MyObj foo = myObjService.findMyObjByProp(prop);
So I need to know if this approach is "better" or more apropiate that calling directly the parent method with the second parameter. E.g:
MyObj foo = (MyObj)myParentObjectService.findObjectByProp(prop, "MyObj");
..and avoiding the creation of second methods, more specific. It is important to know that the children services will be created anyway, because we have lot of code that is specific of a domain objects.
I have the idea that the first approach is better, because is more readable, but I need to support that decision with some documents, blog, or opinions to discuss this designs with my colleagues.
This looks like a tagged class hierarchy. It's difficult to comment on the value of this design in general without knowing the details. However, a slightly different approach that I would recommend is to generify your base class to gain a little bit of type safety.
In particular:
public /* abstract */ class MyParentObjectServiceImpl<T extends MyParentObject>
implements MyParentObjectService{
MyParentObjectServiceImpl(Class<T> type) { this.type = type; }
private final Class<T> type; // subclasses provide this
#Override
public T findObjectByProp(String prop){
//you can use type for object specific stuff
}
}
public class MyObjServiceImpl extends MyParentObjectServiceImpl<MyObj>
// You might not need this interface anymore
// if the only method defined is findMyObjByProp
/* implements MyObjectService */ {
MyObjServiceImpl() {
super(MyObj.class);
}
#Override
public /* final */ MyObj findMyObjByProp(String prop) {
return (MyObj) super.findObjectByProp(prop, this.myObjType);
}
}
You definitely gain in type safety (casting will only appear in the base class), you get rid of the "tags" (the strings that identify the different objects) and possibly reduce the number of classes/interfaces required to implement the whole hierarchy. I successfully used this approach several times. Note that this works best if the base class is abstract. Food for thoughts.

Encapsulating properties in a property/context class

I have created a BicycleProducer interface which has different implementations: OffroadBicycleProducer, FastBicycleProducer and so on.
Each of these factories requires many parameters in order to produce a bicycle. I want to encapsulate these properties in a class and pass it to the produce method. However, the bicycles requires different properties - some may be the same - and I wonder how to do this properly. In the interface of BicycleProducer I have currently a method named produce which takes a parameter BicycleProducingContext which is a interface with all the common properties. And then you have implementations that implement it and add the necassary properties based on what type of bicycle it is. And then you would need to cast it in the produce method....but I don't know. It seem somewhat dodgy (it might not be) I feel.
Is this is a fine approach or should I do it in another way?
public interface BicycleProducer {
void produce(BicycleProducingContext context);
}
public class OffroadBicycleProducer implements BicycleProducer {
public void produce(BicycleProducingContext context) {
context = (OffroadBicycleProducingContext) context;
}
}
and
public interface BicycleProducingContext {
int numberOfBicycles();
void brand(String brand);
}
public class OffroadBycycleProducingContext implements BicycleProducingContext {
//..
}
I find two things sort of awkward about your proposed design:
To me, it looks like you may not need factories (i.e. your Producer classes) at all. Factories are useful when you need to construct an object whose type is not known at compile time. But since you're thinking of having separate factory classes for each type of bicycle (e.g. OffroadBicycleProducer), I assume you do know what kind of object you want to construct ahead of time.
Using a context class to make parameter passing less ugly is a good idea, but if you start creating separate context classes for each type of bicycle, then you end up in the awkward situation of having to know which context to construct as well as what data it requires -- which, if you have all that, you might as well just skip the intermediate step and construct the Bicycle right away.
If I was right in assuming that you do know what kind of object you need to construct ahead of time, then instead of using factories, I would go either with the builder pattern, or with plain old constructors. The constructor approach might look something like the following:
public abstract class Bicycle {
private int year;
private String color;
public Bicycle(BicycleProducingContext context) {
this.year = context.getYear();
this.color = context.getColor();
}
}
public class OffroadBicycle extends Bicycle {
private String terrainType;
public OffroadBicycle(BicycleProducingContext context) {
super(context);
this.terrainType = context.getTerrainType();
}
}
public class FastBicycle extends Bicycle {
private int maxSpeed;
public FastBicycle(BicycleProducingContext context) {
super(context);
this.maxSpeed = context.getMaxSpeed();
}
}
If you don't know what type of Bicycle you want to construct until runtime, then you can use the above approach with a single factory. For example:
public class BicycleFactory {
public static Bicycle constructBicycle(BicycleProducingContext context) {
if (context.getBicycleType().equals("OffroadBicycle")) {
return new OffroadBicycle(context);
} else if (context.getBicycleType().equals("FastBicycle")) {
return new FastBicycle(context);
} else {
throw new IllegalArgumentException("Encountered unrecognized Bicycle type: " + context.getBicycleType());
}
}
}
I hope I'm not over-simplifying your use-case, but it seems to me like the above should accomplish what you're looking for.

Categories