0

this is my code but when I execute the program I get many errors and I don't know why. May anyone help me?

RegisteredUser.java

public class RegisteredUser {
    private String nickname;
    ArrayList<ReviewDAO> reviews;

    public RegisteredUser(String nickname) {
        this.nickname = nickname;
        reviews = new ArrayList<>();
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public void addReview(ReviewDAO review) {
        if (!this.reviews.contains(review)) {
            this.reviews.add(review);
            review.addRegisteredUser(this);
        }
    }

    @Override
    public String toString() {
        return "RegisteredUser{" +
                "nickname='" + nickname + '\'' +
                ", reviews=" + reviews +
                '}';
    }
}

ReviewDAO.java

public abstract class ReviewDAO {
    RegisteredUser registeredUser;

    public abstract boolean write(Review review);

    public void addRegisteredUser(RegisteredUser registeredUser) {
        this.registeredUser = registeredUser;
    }

    @Override
    public String toString() {
        return "ReviewDAO{" +
                "registeredUser=" + registeredUser +
                '}';
    }
}

Review.java

public class Review {
    private String title;
    private String description;
    private int rank;
    private boolean isAnonymous;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public int getRank() {
        return rank;
    }

    public void setRank(int rank) {
        this.rank = rank;
    }

    public boolean isAnonymous() {
        return isAnonymous;
    }

    public void setAnonymous(boolean anonymous) {
        isAnonymous = anonymous;
    }
}

ReviewDAO_MongoDB.java

public class ReviewDAO_MongoDB extends ReviewDAO {
    @Override
    public boolean write(Review review) {
        return false;
        // todo
    }
}

ReviewDAO_Factory.java

public class ReviewDAO_Factory {

    public ReviewDAO getReviewDAO(String technology) throws ExecutionControl.NotImplementedException {
        if (technology.equals("mongodb"))
            return new ReviewDAO_MongoDB();
        else
            throw new ExecutionControl.NotImplementedException("");
    }
}

BusinessLogic.java

public class BusinessLogic {
    public static void main(String[] args) throws ExecutionControl.NotImplementedException {
        ReviewDAO_Factory reviewDAO_factory = new ReviewDAO_Factory();
        RegisteredUser registeredUser = new RegisteredUser("Alessandro");

        registeredUser.addReview(reviewDAO_factory.getReviewDAO("mongodb"));
        System.out.println(registeredUser.toString());
    }
}

I am getting

Exception in thread "main" java.lang.StackOverflowError at RegisteredUser.toString(RegisteredUser.java:33) at java.base/java.lang.String.valueOf(String.java:2951) at ReviewDAO.toString(ReviewDAO.java:15) ...

Process finished with exit code 1

errors

  • 1
    In `RegisteredUser.toString()` you are printing out each `ReviewDAO` that in turn prints out the `RegisteredUser` that in turn prints out each `ReviewDAO` that in turn ... – Seelenvirtuose Jul 13 '20 at 08:34
  • @Seelenvirtuose How can I solve this mistake? –  Jul 13 '20 at 08:35
  • A similar case has been discussed here: https://stackoverflow.com/q/3593893/4636715 . A parent>child>parent... infinite loop. – vahdet Jul 13 '20 at 08:38
  • Does this answer your question? [Avoiding recursion in toString method](https://stackoverflow.com/questions/47606058/avoiding-recursion-in-tostring-method) – Eklavya Jul 13 '20 at 08:41
  • @Eklavya Same errors... what if my code is wrong and not only my overridden toString() method? –  Jul 13 '20 at 08:48
  • @ItsGhost [Printing object calls toString method](https://stackoverflow.com/a/22089315/4207306). So don't use `reviews` or `registeredUser` in toString rather call their field in toString or remove them – Eklavya Jul 13 '20 at 08:52
  • @ItsGhost check my answer. Hope it helps. – Abhinaba Chakraborty Jul 13 '20 at 09:01

1 Answers1

-1

First of all, the design looks faulty. You should never mix POJOs with DAOs. DAOs are "data access object" classes which deals with CRUD operations on the POJOs. Here you have 2 POJOs - Review and RegisteredUser. It's the responsibility of ReviewDAO to perform CRUD operations on managed/unmanaged instances (or entities) of Review. And for RegisteredUser also you need another POJO probably (in your actual code).

Secondly, I see you are calling List contains method to check if the user already has given that review, yet you have not implemented "equals" and "hashCode" in the ReviewDAO.

public void addReview(ReviewDAO review) {
        if (!this.reviews.contains(review)) {
            this.reviews.add(review);
            review.addRegisteredUser(this);
        }
    }

I have made few tweaks. Please check if it satisfies your need:

RegisteredUser class (Have used hashset cause "contains" search will be faster)

public class RegisteredUser {
  private String nickname;
  private Set<Review> reviews;

  public RegisteredUser(String nickname) {
    this.nickname = nickname;
    reviews = new HashSet<>();
  }

  public String getNickname() {
    return nickname;
  }

  public void setNickname(String nickname) {
    this.nickname = nickname;
  }

  public void addReview(Review review) {
    if (!this.reviews.contains(review)) {
      this.reviews.add(review);
      //review.addRegisteredUser(this);
    }
  }

  @Override
  public String toString() {
    return "RegisteredUser{" +
        "nickname='" + nickname + '\'' +
        ", reviews=" + reviews +
        '}';
  }
}

ReviewDAO class:

public abstract class ReviewDAO {
  private RegisteredUser registeredUser;

  public abstract boolean write(Review review);

  public void addRegisteredUser(RegisteredUser registeredUser) {
    this.registeredUser = registeredUser;
  }

}

Review class:

public class Review {
  private String title;
  private String description;
  private int rank;
  private boolean isAnonymous;

  public String getTitle() {
    return title;
  }

  public void setTitle(String title) {
    this.title = title;
  }

  public String getDescription() {
    return description;
  }

  public void setDescription(String description) {
    this.description = description;
  }

  public int getRank() {
    return rank;
  }

  public void setRank(int rank) {
    this.rank = rank;
  }

  public boolean isAnonymous() {
    return isAnonymous;
  }

  public void setAnonymous(boolean anonymous) {
    isAnonymous = anonymous;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o)
      return true;
    if (o == null || getClass() != o.getClass())
      return false;
    Review review = (Review) o;
    return Objects.equals(title, review.title);
  }

  @Override
  public int hashCode() {
    return Objects.hash(title);
  }
}

BusinessLogic class

public class BusinessLogic {
  public static void main(String[] args) throws ExecutionControl.NotImplementedException {
    ReviewDAO_Factory reviewDAO_factory = new ReviewDAO_Factory();

    RegisteredUser registeredUser = new RegisteredUser("Alessandro");

    Review review = new Review();
    review.setTitle("some review");
    review.setDescription("some desc");

    registeredUser.addReview(review);

    ReviewDAO reviewDAO = reviewDAO_factory.getReviewDAO("mongodb");
    reviewDAO.addRegisteredUser(registeredUser);

    System.out.println(registeredUser.toString());
  }
}
Abhinaba Chakraborty
  • 3,488
  • 2
  • 16
  • 37
  • What if I do not override equals and hash in Review.java? and why my design was faulty? –  Jul 13 '20 at 09:06
  • That contains check will not be correct. It will return true only if the two Object references are same (in JVM memory) – Abhinaba Chakraborty Jul 13 '20 at 09:07
  • I have compared two reviews based on their title only. You can add other fields like description too while comparing. – Abhinaba Chakraborty Jul 13 '20 at 09:08
  • and why my design was faulty? –  Jul 13 '20 at 09:09
  • RegisteredUser entity shouldn't be in relation with ReviewDAO instead of Review? –  Jul 13 '20 at 09:10
  • explained it. A POJO should never have a DAO as an instance variable. Rather it should be reverse. Check this out: https://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm#:~:text=Data%20Access%20Object%20concrete%20class,data%20retrieved%20using%20DAO%20class. – Abhinaba Chakraborty Jul 13 '20 at 09:11