samedi 18 novembre 2023

Java multiple datastores return same model

I am trying to solve a multiple data source issue where I need to return the same data model regardless of its source. The multiple data sources are all within their own module with correctly configured beans and config etc... (Redis, JPA, and a Rest-based module), they are all working and return their own respective models currently with associated annotations/validations for the given data source (here lies the issue in terms of why not just re-use the same model class from a common module, we cant as we have loads of logic tied up in their respective annotations).

I could upcast and return the interface, but ideally, I would be able to return the DataModel instead as that is what other applications currently code to alongside its ToString, equals, etc... I could also manually transform and map each field to the data model but I feel like there is some sort of pattern that would help me solve this problem.

So I started to look into the proxy pattern to solve this but the more I read about it the more I think it's not the correct one to follow as i would still end up having to cast etc... Are there any patterns that would help me solve this issue? or should I just upcast and return the interface each time from each resource?

Any advice would be appreciated as I think I am misunderstanding some basic concepts.

Project structure

//Not the exact impl, but you see the idea...

Main app

public interface IFetchData {
 Optional<List<DataModel>> fetchAll();
} 

public class FetchData implements IFetchData {
 private IRedisAccess redis; 
 private IJPAAccess jpa; 
 private IRest rest; 

 public FetchData(IRedisAccess redis, IJPAAccess jpa IRRest rest) {
  this.redis = redis;
  this.jpa = jpa;
  this.rest = rest;
 } 

 public Optional<List<DataModel>> fetchAll() {
  List<DataModel> data;
  data = redis.fetchAll();
  //if not null statement return Optional.of(data);
  data = jpa.fetchAll();
  //if not null statement return Optional.of(data);
  data = rest.fetchAll();
  return Optional.of(data);
 } 
  //more methods for interacting with data interfaces...
} 

Module common

public interface IDataGeneric {
 getId();
 getOtherField1();
} 

@Getter
public class DataModel implements IDataGeneric {
 private long id;
 private String OtherField1;
} 

Module Redis

@Getter
@RedisHash
public class DataModelRedis implements IDataGeneric {
 @Id
 private long id;
 @Index
 private String OtherField1;
}

public interface IRedisAcess{
 Optional<DataModelRedis> fetchId(long id);
 Optional<List<DataModelRedis>> fetchAll();
} 

public class RedisAccess implaments IRedisAcess {
 private RedisRepo redisRepo; 

 public RedisAccess(RedisRepo redisRepo) {
  this.redisRepo = redisRepo;
 } 
 methods for interacting with RedisRepo ...
} 

@Repoistory
public interface RedisRepo extends CrudRepository<DataModelRedis, long>{
 Optional<DataModelRedis> fetchId(long id);
 Optional<List<DataModelRedis>> fetchAll();
} 

Module JPA

@Getter
@Table
@Entity
public class DataModelJPA implements IDataGeneric {
 @Id
 @GeneratedValue
 private long id;
 private String OtherField1;
} 

public interface IJPAAccess{
 Optional<DataModelJPA> fetchId(long id);
 Optional<List<DataModelJPA>> fetchAll();
} 

public class JPAAccess implements IJPAAccess {
 private JPARepo jpaRepo; 

 public jpaAccess(JPARepo jpaRepo) {
  this.jpaRepo = jpaRepo;
 } 
 methods for interacting with jpaRepo ...
} 

@Repoistory
public interface JPARepo extends JPARepository<DataModelJPA, long>{
 Optional<DataModelJPA> fetchId(long id);
 Optional<List<DataModelJPA>> fetchAll();
} 

Aucun commentaire:

Enregistrer un commentaire