javaspringspring-boot

I'm getting null pointers when trying to pull Movie Apis


EXCEPTION

2023-04-07T00:26:53.180+03:00 ERROR 21556 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.NullPointerException: Cannot invoke "com.eray.movieAPI.dto.Results.original_language()" because the return value of "com.eray.movieAPI.dto.MovieResponse.result()" is null] with root cause
java.lang.NullPointerException: Cannot invoke "com.eray.movieAPI.dto.Results.original_language()" because the return value of "com.eray.movieAPI.dto.MovieResponse.result()" is null
    at com.eray.movieAPI.service.MovieService.saveMovieEntity(MovieService.java:54) ~[classes/:na]
    at com.eray.movieAPI.service.MovieService.getMovieFromTheMovieApi(MovieService.java:45) ~[classes/:na]
    at com.eray.movieAPI.service.MovieService.getMovieByTitle(MovieService.java:34) ~[classes/:na]

API CLASSES

public record Results(
        boolean adult,
        String backdrop_path,
        Object belongs_to_collection,
        Integer budget,
        ArrayList<Object> genres,
        String homepage,
        Integer id,
        String imdb_id,
        String original_language,
        String original_title,
        String overview,
        Number popularity,
        String poster_path,
        ArrayList<Object> production_companies,
        ArrayList<Object> production_countries,
        String release_date,
        Integer revenue,
        Integer runtime,
        ArrayList<Object>spoken_languages,
        String status,
        String tagline,
        String title,
        boolean video,
        Number  vote_average,
        Integer vote_count

        ) {
}

public class Page {
    private Integer page;

    public Integer getPage() {
        return page;
    }

    public void setPage(Integer page) {
        this.page = page;
    }

    public Page(Integer page) {
        this.page = page;
    }
}

REPONSE CLASS

@JsonIgnoreProperties(ignoreUnknown = true)
public record MovieResponse (
        Page page,
        Results result) {

}

SERVÄ°CE

@Service
public class MovieService {

    private final ObjectMapper objectMapper = new ObjectMapper();

    private final RestTemplate restTemplate;
    private final MovieRepository movieRepository;

    private String API_URL = "https://api.themoviedb.org/3/search/movie?api_key=66163767a1794185bacde651631ae753&query=";

    public MovieService(RestTemplate restTemplate, MovieRepository movieRepository) {
        this.restTemplate = restTemplate;
        this.movieRepository = movieRepository;
    }

    public MovieDto getMovieByTitle(String title){
        Optional<MovieEntity> movieEntityOptional = movieRepository.findByTitle(title);
        if(!movieEntityOptional.isPresent()){
            return MovieDto.convert(getMovieFromTheMovieApi(title));
        }
            return MovieDto.convert(movieEntityOptional.get());
    }


    private MovieEntity getMovieFromTheMovieApi(String title){
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(API_URL + title, String.class);

        try {
            MovieResponse movieResponse = objectMapper.readValue(responseEntity.getBody(), MovieResponse.class);
            return saveMovieEntity(title , movieResponse);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

    }

    private MovieEntity saveMovieEntity(String title, MovieResponse movieResponse){
        MovieEntity movieEntity = new MovieEntity(
               movieResponse.result().original_language(),
                movieResponse.result().original_title(),
                movieResponse.result().release_date(),
                movieResponse.result().overview(),
                movieResponse.result().popularity(),
                movieResponse.page().getPage()
                );
        return movieRepository.save(movieEntity);
    }

MOVIE ENTITY

@Entity
public class MovieEntity {

    @Id
    @GeneratedValue(generator = "UUID")
    @GenericGenerator(name = "UUID" , strategy = "org.hibernate.id.UUIDGenerator")
    private String id;

    private String language;

    private String title;

    private String releaseDate;

    private String overview;

    private Number popularity;

    private Integer page;

MOVIE DTO


public record MovieDto(

         String language,

         String title,

         String releaseDate,

         String overview,

         Number popularity

) {
    public static MovieDto convert(MovieEntity from){
        return new MovieDto(from.getLanguage(),
                from.getTitle(),
                from.getReleaseDate(),
                from.getOverview(),
                from.getPopularity());
    }

CONTROLLER

@RestController
@RequestMapping("/v1/api/movie")
public class MovieController {

    private final MovieService movieService;


    public MovieController(MovieService movieService) {
        this.movieService = movieService;
    }

    @GetMapping("/{title}")
    public ResponseEntity<MovieDto> getMovieByMovieTitle(@PathVariable @NotBlank String title){
        return ResponseEntity.ok(movieService.getMovieByTitle(title));
    }

API


{
  "page": 1,
  "results": [
    {
      "adult": false,
      "backdrop_path": "/2v3pC01rf0uXnECOM94pjfqk1TY.jpg",
      "genre_ids": [
        80,
        18,
        53,
        28
      ],
      "id": 75780,
      "original_language": "en",
      "original_title": "Jack Reacher",
      "overview": "When a gunman takes five lives with six shots, all evidence points to the suspect in custody. On interrogation, the suspect offers up a single note: \"Get Jack Reacher!\" So begins an extraordinary chase for the truth, pitting Jack Reacher against an unexpected enemy, with a skill for violence and a secret to keep.",
      "popularity": 62.348,
      "poster_path": "/uQBbjrLVsUibWxNDGA4Czzo8lwz.jpg",
      "release_date": "2012-12-20",
      "title": "Jack Reacher",
      "video": false,
      "vote_average": 6.587,
      "vote_count": 6235
    },
    {
      "adult": false,
      "backdrop_path": "/ww1eIoywghjoMzRLRIcbJLuKnJH.jpg",
      "genre_ids": [
        28,
        53
      ],
      "id": 343611,
      "original_language": "en",
      "original_title": "Jack Reacher: Never Go Back",
      "overview": "When Major Susan Turner is arrested for treason, ex-investigator Jack Reacher undertakes the challenging task to prove her innocence and ends up exposing a shocking conspiracy.",
      "popularity": 54.436,
      "poster_path": "/cOg3UT2NYWHZxp41vpxAnVCOC4M.jpg",
      "release_date": "2016-10-19",
      "title": "Jack Reacher: Never Go Back",
      "video": false,
      "vote_average": 5.925,
      "vote_count": 4322
    },
    {
      "adult": false,
      "backdrop_path": null,
      "genre_ids": [
        99
      ],
      "id": 1045592,
      "original_language": "en",
      "original_title": "Jack Reacher: When the Man Comes Around",
      "overview": "Cast and crew speak on adapting One Shot as the first Jack Reacher film, casting Tom Cruise, earning Lee Child's blessing, additional character qualities and the performances that shape them, Lee Child's cameo in the film, and shooting the film's climax.",
      "popularity": 5.992,
      "poster_path": null,
      "release_date": "2013-05-07",
      "title": "Jack Reacher: When the Man Comes Around",
      "video": false,
      "vote_average": 10.0,
      "vote_count": 1
    }
  ],
  "total_pages": 1,
  "total_results": 3
}
@JsonIgnoreProperties(ignoreUnknown = true)
  error when i remove


2023-04-07T00:40:07.691+03:00 ERROR 15896 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "results" (class com.eray.movieAPI.dto.MovieResponse), not marked as ignorable (2 known properties: "result", "page"])
 at [Source: (String)"{"page":1,"results":[{"adult":false,"backdrop_path":"/2v3pC01rf0uXnECOM94pjfqk1TY.jpg","genre_ids":[80,18,53,28],"id":75780,"original_language":"en","original_title":"Jack Reacher","overview":"When a gunman takes five lives with six shots, all evidence points to the suspect in custody. On interrogation, the suspect offers up a single note: \"Get Jack Reacher!\" So begins an extraordinary chase for the truth, pitting Jack Reacher against an unexpected enemy, with a skill for violence and a secret"[truncated 1353 chars]; line: 1, column: 1854] (through reference chain: com.eray.movieAPI.dto.MovieResponse["results"])] with root cause

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "results" (class com.eray.movieAPI.dto.MovieResponse), not marked as ignorable (2 known properties: "result", "page"])
 at [Source: (String)"{"page":1,"results":[{"adult":false,"backdrop_path":"/2v3pC01rf0uXnECOM94pjfqk1TY.jpg","genre_ids":[80,18,53,28],"id":75780,"original_language":"en","original_title":"Jack Reacher","overview":"When a gunman takes five lives with six shots, all evidence points to the suspect in custody. On interrogation, the suspect offers up a single note: \"Get Jack Reacher!\" So begins an extraordinary chase for the truth, pitting Jack Reacher against an unexpected enemy, with a skill for violence and a secret"[truncated 1353 chars]; line: 1, column: 1854] (through reference chain: com.eray.movieAPI.dto.MovieResponse["results"])
    at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61) ~[jackson-databind-2.14.2.jar:2.14.2]
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:1132) ~[jackson-databind-2.14.2.jar:2.14.2]
    at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:2202) ~[jackson-databind-2.14.2.jar:2.14.2]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:540) ~[jackson-databind-2.14.2.jar:2.14.2]com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1705) ~[jackson-databind-2.14.2.jar:2.14.2]
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperties(BeanDeserializerBase.java:1655) ~[jackson-databind-2.14.2.jar:2.14.2]
    at 
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1405) ~[jackson-databind-2.14.2.jar:2.14.2]

Solution

  • Your MovieResponse has the field called result. According the Api it needs to be called results and should be a list.

    also as a tip, you should not post your api-key in the question.