Skip to content

RESTful API with data persistence built in Java using Spring and Spring Data JPA

Notifications You must be signed in to change notification settings

Meekb/Java_DiningReviews

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

56 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Dining Reviews in Java

An allergy-specific restaurant review API built to solidfy the fundamentals of Java and Spring

Overview

RESTful Dining Review API with data persistence built in Java using Spring and Spring Data JPA with Hibernate.
This sample Dining Review API is designed for folks with allergies. Users indicate interest in any or all of three categories - peanut, egg, dairy. Restaurants are rated in each category and have an overall rating which is the average of all review scores. Reviews contain username and optional scores for peanut, egg, dairy, as well as an optional commentary.

Instructions

You will need an Integrated Develepor Environment (IDE) such as IntelliJ IDE, or VS Code and a Java Development Kit (JDK) version 8 or higher. From the command line:

git clone git@github.com:Meekb/Java_DiningReviews.git <project name>
cd <project name>
npm install

Open project in IDE, run local server to curl endpoints

Model:

The Model consists of four classes - User, Restaurant, DiningReview, and AdminReviewStatus.

  • User, Restaurant, and DingingReview classes have an auto-generated id, date type Long
Code samples from DiningReview and AdminReviewStatus Classes
@Entity
@Table(name = "REVIEWS")
public @Data
@NoArgsConstructor
class DiningReview {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  @Column(name = "USERNAME")
  private String username;
  @Column(name = "RESTAURANT")
  private Long restaurant; // represented by the restaurant id
  @Column(name = "PEANUTSCORE")
  private Integer peanutScore;
  @Column(name = "EGGSCORE")
  private Integer eggScore;
  @Column(name = "DAIRYSCORE")
  private Integer dairyScore;
  @Column(name = "COMMENTARY")
  private String commentary;
  @Column(name = "REVIEW_STATUS")
  @Enumerated(EnumType.STRING)
  private AdminReviewStatus adminReviewStatus;
}

AdminReviewStatus

public enum AdminReviewStatus {
    PENDING,
    APPROVED,
    REJECTED,
}

Controller:

Three controllers - UserController, RestaurantController, DiningReviewController

Code samples from UserController
// creates / saves a new user
 @PostMapping("/addNew")
 public User createUser(@RequestBody User user) {
     if (userRepository.getByUsername(user.getUsername()) != null && userRepository.findById(user.getId()).isPresent()) {
         System.out.print("\nUser already exists");
         throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "User already exists");
     }
     if (userRepository.getByUsername(user.getUsername()) != null) {
         System.out.print("\nUsername not available");
         throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Username not available");
     }
     return userRepository.save(user);
 }

// returns users with peanut allergy interest
 @GetMapping("/peanut_allergy")
 public Iterable <User> findByPeanutInterestTrue() {
     return this.userRepository.getByPeanutInterestTrue();
 }
Code samples from RestaurantController
// returns restaurant Optional or ResponseStatusException
 @GetMapping("/name_{name}")
  public Optional<Restaurant> getRestaurantByName(@PathVariable("name") String name) {
      Optional<Restaurant> restaurantOptional = this.restaurantRepository.findByNameContaining(name);
      if (restaurantOptional.isEmpty()) {
          System.out.print("No Restaurants found by that name.");
          throw new ResponseStatusException(HttpStatus.NOT_FOUND, "No Restaurants found with that name.");
      } else return restaurantOptional;
  }

 // creates and saves a new restaurant
 @PostMapping("/addNew")
  public Restaurant createNewRestaurant(@RequestBody Restaurant restaurant) {
      if (restaurantRepository.findByNameContaining(restaurant.getName()).isEmpty()) {
          Restaurant newRestaurant = restaurantRepository.save(restaurant);
          System.out.print("\nNew restaurant created! id: " +  newRestaurant.getId() + ", name: " + newRestaurant.getName());
          return newRestaurant;
      } else throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Restaurant may already exist...");
  }

 // returns List of restaurants with overall rating greater than or equal to requested
 @GetMapping("/overallRating_{overallRating}")
 public List<Restaurant> getByOverallGreaterThanEqual(@PathVariable("overallRating") Double overallRating) {
     List<Restaurant> restaurantsToReturn = this.restaurantRepository.findByOverallRatingGreaterThanEqual(overallRating);
     if (restaurantsToReturn.isEmpty()) {
         System.out.print("\nSorry, no restaurants found with that overall rating.");
         throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Sorry, no restaurants found with that overall rating.");
     } else return restaurantsToReturn;
 }
Code samples from DiningReviewController
// returns review list with requested min dairy score
 @GetMapping("/dairyScore_{dairyScore}")
 public Iterable<DiningReview> getReviewsByDairyScoreGreaterThanEqual(@PathVariable("dairyScore") Integer dairyScore) {
     Iterable<DiningReview> resultList = diningReviewRepository.findByDairyScoreGreaterThanEqual(dairyScore);
     if (resultList != null) {
         return diningReviewRepository.findByDairyScoreGreaterThanEqual(dairyScore);
     } else return new ArrayList<>();
 }

// creates and saves and new DiningReview with ResponseStatusExceptions for invalid user and restaurant id
@PostMapping("/addNew")
 public DiningReview createNewDiningReview(@RequestBody DiningReview diningReview) {
     if (restaurantRepository.findById(diningReview.getRestaurant()).isEmpty()) {
         throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Restaurant does not exist");
     }
     if (userRepository.getByUsername(diningReview.getUsername()) == null) {
         throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "User does not exist");
     }
     DiningReview newReview = diningReview;
     newReview.setAdminReviewStatus(AdminReviewStatus.PENDING);
     return diningReviewRepository.save(newReview);
 }
 
 // returns all reviews sorted by username
 @GetMapping("/sorted_username")
 public Iterable<DiningReview> getAllDiningReviewsSorted() {
     return diningReviewRepository.findAll(Sort.by("username"));
 }  
  
// The following three endpoints return an Iterable of reviews by AdminReviewStatus Pending, Approved, Rejected
 @GetMapping("/pending")
 public Iterable<DiningReview> getPendingReviews() {
     return this.diningReviewRepository.findByAdminReviewStatus(AdminReviewStatus.PENDING);
 }
 @GetMapping("/approved")
 public Iterable<DiningReview> getApprovedReviews() {
     return this.diningReviewRepository.findByAdminReviewStatus(AdminReviewStatus.APPROVED);
 }
 @GetMapping("/rejected")
 public Iterable<DiningReview> getRejectedReviews() {
     return this.diningReviewRepository.findByAdminReviewStatus(AdminReviewStatus.REJECTED);
 }
 
 // approves a pending review
 @PutMapping("/admin_approve/{id}")
 public DiningReview approveReview(@PathVariable("id") Long id) {
     Optional<DiningReview> reviewToChangeOptional = diningReviewRepository.findById(id);
     if (reviewToChangeOptional.isEmpty()) {
         System.out.print("Review does not exist");
         throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Review id does not exist");
     } else {
         DiningReview reviewToChange = reviewToChangeOptional.get();
         reviewToChange.setAdminReviewStatus(AdminReviewStatus.APPROVED);
         diningReviewRepository.save(reviewToChange);
         return reviewToChange;
     }
 }
 
 // deletes a rejected review
 @DeleteMapping("/delete_rejected/{id}")
 public DiningReview deleteRejectedDiningReview(@PathVariable("id") Long id) {
     Optional<DiningReview> reviewToDeleteOptional = diningReviewRepository.findById(id);
     if (!reviewToDeleteOptional.isPresent()) {
         return null;
     }
     DiningReview reviewToDelete = reviewToDeleteOptional.get();
     diningReviewRepository.delete(reviewToDelete);
     System.out.print("\nid: " + id + " has been successfully deleted");
     return reviewToDelete;
 }

Repositories:

Repositories for User, Restaurant, DiningReview

Code sample from User Repository
public interface UserRepository extends CrudRepository<User, Long> {
  User getByUsername(String username);
  Iterable <User> getByPeanutInterestTrue();
  Iterable <User> getByEggInterestTrue();
  Iterable <User> getByDairyInterestTrue();
}
Code sample from Restaurant Repository
public interface RestaurantRepository extends CrudRepository<Restaurant, Long> {
  List<Restaurant> findAll(Sort name);
  List<Restaurant> findByNameContaining(String name);
  List<Restaurant> findByOverallRatingGreaterThanEqual(Double overallRating);
  List<Restaurant> findByPeanutRatingGreaterThanEqual(Integer peanutRating);
  List<Restaurant> findByEggRatingGreaterThanEqual(Integer eggRating);
  List<Restaurant> findByDairyRatingGreaterThanEqual(Integer dairyRating);
}
Code sample from DiningReview Repository
public interface DiningReviewRepository extends CrudRepository<DiningReview, Long> {
  Iterable<DiningReview> findByAdminReviewStatus(AdminReviewStatus adminReviewStatus);
  Iterable<DiningReview> findByPeanutScoreGreaterThanEqual(Integer peanutScore);
  Iterable<DiningReview> findByEggScoreGreaterThanEqual(Integer eggScore);
  Iterable<DiningReview> findByDairyScoreGreaterThanEqual(Integer dairyScore);
}

Tech Stack

Java Spring Hibernate IntelliJ IDE

Contributors

Beth Meeker GH
Beth Meeker avatar

About

RESTful API with data persistence built in Java using Spring and Spring Data JPA

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages