Skip to content

Commit

Permalink
Merge pull request #26 from neuefische/ISSUE-12
Browse files Browse the repository at this point in the history
ISSUE-12: Create a POST create new relation actor-movie-relation endpoint and cover it with tests.
  • Loading branch information
Krisssssssssssssssssssssss authored Oct 17, 2024
2 parents f2c2e83 + 0f90841 commit a136757
Show file tree
Hide file tree
Showing 18 changed files with 388 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,6 @@ public void getByNameInvalid() throws NoResourceFoundException {
throw new NoResourceFoundException(HttpMethod.GET, "/api/actor/autocompletion/");
}

@GetMapping("/movie/{movieId}")
public List<ActorResponse> getByMovieId(@PathVariable @NonNull Long movieId) {
return actorService.getActorsByMovieId(movieId).stream().map(ActorResponse::from).toList();
}

/**
* Prevents the frontend fallback response from being returned if the request path is invalid.
*
* @throws NoResourceFoundException
*/
@GetMapping("/movie/")
public void getByMovieIdInvalid() throws NoResourceFoundException {
throw new NoResourceFoundException(HttpMethod.GET, "/api/actor/movie/");
}

@PutMapping
public void update() {
// TODO
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.example.backend.controller;

import com.example.backend.dto.ActorResponse;
import com.example.backend.dto.MovieActorRequest;
import com.example.backend.service.MovieActorService;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.resource.NoResourceFoundException;

import java.util.List;

@RestController
@AllArgsConstructor
@RequestMapping("/api/movie-actor")
public class MovieActorController {

private final MovieActorService movieActorService;

@PostMapping()
public void addActorById(@RequestBody @NonNull MovieActorRequest movieActorRequest) {
movieActorService.addActor(movieActorRequest.movieId(), movieActorRequest.actorId());
}

@GetMapping("/{movieId}")
public List<ActorResponse> getActorsByMovieId(@PathVariable @NonNull Long movieId) {
return movieActorService.getActorsByMovieId(movieId).stream().map(ActorResponse::from).toList();
}

/**
* Prevents the frontend fallback response from being returned if the request path is invalid.
*
* @throws NoResourceFoundException
*/
@GetMapping("/")
public void getByMovieIdInvalid() throws NoResourceFoundException {
throw new NoResourceFoundException(HttpMethod.GET, "/api/actor-movie/");
}}
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ public class MovieController {
private final MovieService movieService;

@PostMapping
public MovieResponse save(@RequestBody @NotNull CreateMovieRequest movieRequest){
public MovieResponse save(@RequestBody @NotNull CreateMovieRequest movieRequest) {
Movie movie = movieRequest.toMovie();
return MovieResponse.from(movieService.createMovie(movie));
}

@GetMapping
public List<MovieResponse> getAll(){
public List<MovieResponse> getAll() {
return movieService.getAllMovies().stream().map(MovieResponse::from).collect(Collectors.toList());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.example.backend.dto;

public record ErrorResponse(String message) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.example.backend.dto;

import lombok.NonNull;

public record MovieActorRequest(@NonNull Long movieId, @NonNull Long actorId) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.example.backend.exception;

import com.example.backend.dto.ErrorResponse;
import lombok.extern.log4j.Log4j2;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.resource.NoResourceFoundException;

import java.util.NoSuchElementException;
import java.util.logging.Logger;

@ControllerAdvice
@Log4j2
public class GlobalExceptionHandler {
private static final String GENERIC_ERROR_MESSAGE = "Something went wrong";

@ExceptionHandler
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleGlobalException(NoSuchElementException exception) {
log.info(exception.getMessage());
return new ErrorResponse(exception.getMessage());
}

@ExceptionHandler
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleGlobalException(HttpMessageNotReadableException exception) {
log.info(exception.getMessage());
return new ErrorResponse(exception.getMessage());
}

@ExceptionHandler
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorResponse handleGlobalException(NoResourceFoundException exception) {
log.info(exception.getMessage());
return new ErrorResponse(exception.getMessage());
}

@ExceptionHandler
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorResponse handleGlobalException(Exception exception) {
log.error(exception);
return new ErrorResponse(GENERIC_ERROR_MESSAGE);
}
}
4 changes: 1 addition & 3 deletions backend/src/main/java/com/example/backend/model/Actor.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import jakarta.persistence.*;
import lombok.*;

import java.util.HashSet;
import java.util.Set;

@Entity
Expand All @@ -17,9 +18,6 @@ public class Actor {
@GeneratedValue
private Long id;

@ManyToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER)
private Set<Movie> movies;

@Column(nullable = false)
private String name;
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
package com.example.backend.model;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface ActorRepository extends JpaRepository<Actor, Long> {
List<Actor> findByNameStartingWith(String prefix);

@Query("SELECT a FROM Actor a JOIN a.movies m WHERE m.id = :movieId")
List<Actor> findByMovieId(@Param("movieId") Long movieId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import jakarta.persistence.*;
import lombok.*;

import java.util.HashSet;
import java.util.Set;

@Entity
Expand All @@ -17,8 +18,5 @@ public class Director {
@GeneratedValue
private Long id;

@ManyToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER)
private Set<Movie> movies;

private String name;
}
7 changes: 1 addition & 6 deletions backend/src/main/java/com/example/backend/model/Movie.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import jakarta.persistence.*;
import lombok.*;

import java.util.HashSet;
import java.util.Set;

@Entity
Expand All @@ -22,11 +23,5 @@ public class Movie {

private boolean isWatched;

@ManyToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER)
private Set<Actor> actors;

@ManyToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER)
private Set<Director> directors;

private String name;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.example.backend.model;

import jakarta.persistence.*;
import lombok.*;

@Entity
@AllArgsConstructor
@NoArgsConstructor
@Builder
@With
@Data
@Table(
uniqueConstraints = {
@UniqueConstraint(columnNames = {"actor_id", "movie_id"})
}
)
public class MovieActorRelation {
@Id
@GeneratedValue
private Long id;

@ManyToOne(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH})
private Actor actor;

@ManyToOne(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH})
private Movie movie;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.example.backend.model;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface MovieActorRelationRepository extends JpaRepository<MovieActorRelation, Long> {
List<MovieActorRelation> findByMovieId(Long movieId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,4 @@ public List<Actor> getAllActors() {
public List<Actor> getActorsByPrefix(String prefix) {
return actorRepository.findByNameStartingWith(prefix);
}

public List<Actor> getActorsByMovieId(Long movieId) {
return actorRepository.findByMovieId(movieId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.example.backend.service;

import com.example.backend.model.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RequiredArgsConstructor
public class MovieActorService {
private final MovieActorRelationRepository movieActorRelationRepository;

private final ActorRepository actorRepository;

private final MovieRepository movieRepository;

public List<Actor> getActorsByMovieId(Long movieId) {
return movieActorRelationRepository.findByMovieId(movieId)
.stream()
.map(MovieActorRelation::getActor)
.toList();
}

public void addActor(Long movieId, Long actorId) {
Movie movie = movieRepository.findById(movieId).orElseThrow();
Actor actor = actorRepository.findById(actorId).orElseThrow();
movieActorRelationRepository.save(MovieActorRelation.builder().actor(actor).movie(movie).actor(actor).build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@

import com.example.backend.model.Movie;
import com.example.backend.model.MovieRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;

import java.util.List;

Expand All @@ -18,26 +15,24 @@ public class MovieService {
public Movie createMovie(Movie movie) {
return movieRepository.save(movie);
}

public List<Movie> getAllMovies() {
return movieRepository.findAll();
}

public Movie getMovieById(Long movieId) {
return movieRepository.findById(movieId)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Movie with id " + movieId + " not found"));
return movieRepository.findById(movieId).orElseThrow();
}

public void deleteMovie(Long movieId) {
if (movieRepository.existsById(movieId)) {
movieRepository.deleteById(movieId);
} else {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Movie with id " + movieId + " does not exist");
}
Movie movie = movieRepository.findById(movieId).orElseThrow();

movieRepository.delete(movie);
}

public Movie updateMovie(Movie movie) {
if (movieRepository.existsById(movie.getId())) {
return movieRepository.save(movie);
}
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Movie with id " + movie.getId() + " does not exist");
movieRepository.findById(movie.getId()).orElseThrow();

return movieRepository.save(movie);
}
}
Loading

0 comments on commit a136757

Please sign in to comment.