Skip to content
This repository has been archived by the owner on Jan 14, 2024. It is now read-only.

Unified DAO #95

Open
aroquev00 opened this issue Jul 31, 2020 · 2 comments
Open

Unified DAO #95

aroquev00 opened this issue Jul 31, 2020 · 2 comments

Comments

@aroquev00
Copy link
Contributor

Brett's single DAO vision

@brettapeters
Copy link
Contributor

... In the Land of Mordor where the Shadows lie.
One DAO to rule them all, One DAO to find them,
One DAO to bring them all, and in the ServletContextListener bind them...

@brettapeters
Copy link
Contributor

brettapeters commented Aug 5, 2020

This is the general half-formed idea.

// Dao.java
public interface Dao<T> {
  Future<T> get(GetRequest<T> request);

  Future<PagedResponse<T>> list(ListRequest<T> request);

  Future<T> create(CreateRequest<T> request);

  Future<T> update(UpdateRequest<T> request);

  Future<Void> delete(DeleteRequest<T> request);
}
// GetRequest.java
public abstract class GetRequest<T> {
  // Prevent direct instantiation
  GetRequest() {
  }

  public abstract Class<T> payloadType();

  public abstract ResourceUri uri();

  public static <T> Builder<T> builder(Class<T> payloadType) {
    return new AutoValue_GetRequest.Builder<T>().setPayloadType(payloadType);
  }

  @AutoValue.Builder
  public abstract static class Builder<T> {
    // Prevent direct instantiation
    Builder() {
    }

    abstract Builder<T> setPayloadType(Class<T> payloadClass);

    public abstract Builder<T> setUri(ResourceUri uri);

    public abstract GetRequest<T> build();
  }
}
// ResourceUri.java
@AutoValue
public abstract class ResourceUri {
  // Prevent direct instantiation
  ResourceUri() {
  }

  public abstract String path();

  public static Builder builder() {
    return new AutoValue_ResourceUri.Builder();
  }

  @AutoValue.Builder
  public abstract static class Builder {
    // Prevent direct instantiation
    Builder() {
    }

    public abstract Builder setPath(String path);

    public abstract ResourceUri build();
  }
}
// FirebaseDao.java
public abstract class FirestoreDao<R> implements Dao<R> {

  private Firestore db;

  public FirestoreDao(Firestore db) {
    this.db = db;
  }

  @Override
  public Future<R> get(GetRequest<R> request) {
    DocumentReference docRef = db.document(request.uri().path());
    return ApiFutures.transform(docRef.get(), (snapshot) -> snapshot.toObject(request.payloadType()), directExecutor());
  }
  
  // Other method implementations

  // Probably need some protected methods overridden in subclasses to help with conversion
  // between Firestore and POJOs.
}
// QuestionDao.java
public class QuestionDao extends FirestoreDao<Question> {

  public QuestionDao(Firestore db) {
    super(db);
  }

  // Overridden protected methods from FirestoreDao superclass.
}
// QuestionServlet.java
public class QuestionServlet extends HttpServlet {

  private final Dao<Question> dao;

  @Inject
  QuestionServlet(Dao<Question> dao) {
    this.dao = dao;
  }

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String questionPath = String.format("question%s", req.getPathInfo());
    ResourceUri uri = ResourceUri.builder().setPath(questionPath).build();
    GetRequest<Question> request = GetRequest.<Question>builder(Question.class).setUri(uri).build();

    Future<Question> future = dao.get(request);

    try {
      Question question = future.get();
      resp.getWriter().println(question.questionText());
    } catch (InterruptedException | ExecutionException e) {
      logger.warning(e.toString());
    }
  }
}
// GET "/questions/{questionId}"

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants