#359 Code Review of an Author Search API

Companies:
T-Bank RightLine
Themes:
SpringSpring Data JPATransactionsCode Review

Perform a code review:

/**
  * API for searching authors and their books by author name, either a full name or a partial name in any case.
  * The component also updates statistics for the search-string usage frequency on every search; another system resets it once per day.
  * When a popular query is detected (> 1000 requests per day) and it returns many authors, an alert is sent.
  * An alert must be sent no more than once per day for each query.
  * The classes are actually stored in separate files but are shown together here for convenience.
*/
@RestController
public class AuthorController {
    @Autowired
    private AuthorSearchService service;

    @GetMapping("/authors")
    public List<AuthorDto> readAllAuthors(@RequestParam String query) {
        List<Author> authors = service.search(query);
        return authors.stream().map(el -> {
            return new Mapper().map(el);
        }).collect(Collectors.toList());
    }
}

@Component
public class AuthorSearchService {

    @Autowired
    private AuthorsRepository authorsRepository;
    @Autowired
    private StatisticsRepository statisticsRepository;

    private AlertRestClient arc = new AlertRestClient();

    // query may contain either the full name or a partial name, for example "Vadim Panov" or "panov"
    @Transactional
    public List<Author> search(String query) {
        List<Author> authors = authorsRepository.findByNameContainingIgnoreCase(query);
        Statistics s = statisticsRepository.findById(query).orElse(null);
        if (s == null) s = new Statistics(query);
        s.setNumbers(s.getNumbers() + 1);
        statisticsRepository.save(s);
        if (s.getNumbers() > 1000 && authors.size() > 1000) {
            System.out.println("too popular search with too much data, sending an alert...");
            arc.send(query, s.getNumbers(), authors.size());
        }

        return authors;
    }
}


@Entity
@Data
public class Author {
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @OneToMany(mappedBy = "author")
    private List<Book> books;

    public Author(String name) {
        this.name = name;
    }
}

@Entity
@Data
public class Statistics {
    @Id
    private String query;
    private int numbers;

    public Statistics(String query) {
        this.query = query;
    }
}


@Data
public class AuthorDto {
    private Long id;
    private String name;
    private List<Book> books;
}


@Entity
@Data
public class Book {
    private Long id;
    private String name;
}

Question review

Mentor
Answer as you would in a real interview. I’ll ask follow-up questions, then compare your answer with the reference answer and show your accuracy as a %.
Sign in to start the dialogue The mentor keeps the context of the current question and your previous messages.
Sign in