Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rick and Morty First Commit #43

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 66 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,58 @@
<maven.checkstyle.plugin.configLocation>
https://raw.githubusercontent.com/mate-academy/style-guides/master/java/checkstyle.xml
</maven.checkstyle.plugin.configLocation>

<spring.boot.maven.plugin.version>3.1.2</spring.boot.maven.plugin.version>
<maven.compiler.plugin.version>3.11.0</maven.compiler.plugin.version>
<mapstruct.version>1.5.5.Final</mapstruct.version>
<lombok.mapstruct.binding.version>0.2.0</lombok.mapstruct.binding.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.1.0</version>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let spring to manage version

Suggested change
<version>8.1.0</version>

</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>

<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies>

Expand All @@ -48,6 +79,7 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.maven.plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand All @@ -66,9 +98,40 @@
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<linkXRef>false</linkXRef>
<sourceDirectories>src</sourceDirectories>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${lombok.mapstruct.binding.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<compilerArg>
-Amapstruct.unmappedTargetPolicy=IGNORE
</compilerArg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>

</project>
15 changes: 15 additions & 0 deletions src/main/java/mate/academy/rickandmorty/Application.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
package mate.academy.rickandmorty;

import java.util.List;
import mate.academy.rickandmorty.dto.CharacterResponseDto;
import mate.academy.rickandmorty.service.CharacterService;
import mate.academy.rickandmorty.service.RickAndMortyClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
private static RickAndMortyClient rickAndMortyClient;
private static CharacterService characterService;

@Autowired
public Application(CharacterService service, RickAndMortyClient client) {
Application.rickAndMortyClient = client;
Application.characterService = service;
}
Comment on lines +15 to +22
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Application is responsible for booting your app.
Not for the characterService.saveAll(characters);
SRP violates here.

Consider using CommanLineRunner or ApplicationRunner.

Suggested change
private static RickAndMortyClient rickAndMortyClient;
private static CharacterService characterService;
@Autowired
public Application(CharacterService service, RickAndMortyClient client) {
Application.rickAndMortyClient = client;
Application.characterService = service;
}


public static void main(String[] args) {
SpringApplication.run(Application.class, args);
List<CharacterResponseDto> characters = rickAndMortyClient.getCharacters();
characterService.saveAll(characters);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package mate.academy.rickandmorty.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import lombok.RequiredArgsConstructor;
import mate.academy.rickandmorty.dto.CharacterDto;
import mate.academy.rickandmorty.service.CharacterService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Tag(name = "Character management", description = "Endpoints for getting characters from DB")
@RequiredArgsConstructor
@RestController
public class CharacterController {
private final CharacterService characterService;

@Operation(summary = "Get random character",
description = "Get a random characters from Rick and Morty world")
@GetMapping("/random")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

REST URI convention violates here.

Suggested change
@GetMapping("/random")
@GetMapping

public CharacterDto getRandomCharacter() {
return characterService.getRandomCharacter();
}

@Operation(summary = "Search characters",
description = "Search characters by name")
@GetMapping("/search")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recall the REST URI convention.

Suggested change
@GetMapping("/search")
@GetMapping

public List<CharacterDto> searchCharacter(@RequestParam String name) {
return characterService.findByName(name);
}
}
12 changes: 12 additions & 0 deletions src/main/java/mate/academy/rickandmorty/dto/CharacterDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package mate.academy.rickandmorty.dto;

import lombok.Data;

@Data
public class CharacterDto {
private Long id;
private String externalId;
private String name;
private String status;
private String gender;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package mate.academy.rickandmorty.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;

@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public class CharacterResponseDto {
private Long id;
private String name;
private String status;
private String gender;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package mate.academy.rickandmorty.dto;

import java.util.List;
import lombok.Data;

@Data
public class ListCharacterDto {
private List<CharacterResponseDto> results;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package mate.academy.rickandmorty.mapper;

import mate.academy.rickandmorty.dto.CharacterDto;
import mate.academy.rickandmorty.dto.CharacterResponseDto;
import mate.academy.rickandmorty.model.Character;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper(componentModel = "spring")
public interface CharacterMapper {
@Mapping(source = "id", target = "externalId")
@Mapping(target = "id", ignore = true)
Character toModel(CharacterResponseDto responseDto);

CharacterDto toDto(Character character);
}
21 changes: 21 additions & 0 deletions src/main/java/mate/academy/rickandmorty/model/Character.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package mate.academy.rickandmorty.model;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;

@Data
@Entity
@Table(name = "characters")
public class Character {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String externalId;
private String name;
private String status;
private String gender;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package mate.academy.rickandmorty.repository;

import java.util.List;
import mate.academy.rickandmorty.model.Character;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@repository is redundant here.

Suggested change
@Repository

public interface CharacterRepository extends JpaRepository<Character, Long> {
List<Character> findByNameContaining(String name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package mate.academy.rickandmorty.service;

import java.util.List;
import mate.academy.rickandmorty.dto.CharacterDto;
import mate.academy.rickandmorty.dto.CharacterResponseDto;

public interface CharacterService {
CharacterDto getRandomCharacter();

void saveAll(List<CharacterResponseDto> listDto);

List<CharacterDto> findByName(String name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package mate.academy.rickandmorty.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.List;
import lombok.RequiredArgsConstructor;
import mate.academy.rickandmorty.dto.CharacterResponseDto;
import mate.academy.rickandmorty.dto.ListCharacterDto;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class RickAndMortyClient {
private static final String CHARACTER_URL = "https://rickandmortyapi.com/api/character";
private final ObjectMapper objectMapper;

public List<CharacterResponseDto> getCharacters() {
HttpClient httpClient = HttpClient.newHttpClient();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make HttpClient the spring bean.
It shouldnt be created every method invokation.

Suggested change
HttpClient httpClient = HttpClient.newHttpClient();
HttpClient httpClient = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(URI.create(CHARACTER_URL))
.build();
try {
HttpResponse<String> response = httpClient
.send(request, HttpResponse.BodyHandlers.ofString());
ListCharacterDto listCharacterDto = objectMapper
.readValue(response.body(), ListCharacterDto.class);
return listCharacterDto.getResults();
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add method description here.

Suggested change
throw new RuntimeException(e);
throw new RuntimeException(e);

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package mate.academy.rickandmorty.service.impl;

import java.util.List;
import java.util.Random;
import lombok.RequiredArgsConstructor;
import mate.academy.rickandmorty.dto.CharacterDto;
import mate.academy.rickandmorty.dto.CharacterResponseDto;
import mate.academy.rickandmorty.mapper.CharacterMapper;
import mate.academy.rickandmorty.model.Character;
import mate.academy.rickandmorty.repository.CharacterRepository;
import mate.academy.rickandmorty.service.CharacterService;
import org.springframework.stereotype.Service;

@RequiredArgsConstructor
@Service
public class CharacterServiceImpl implements CharacterService {
private int listSize;
private final Random random = new Random();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are using spring, so such instantiations is bad practice.
COnsider making random the spring bean.

Suggested change
private final Random random = new Random();
private final Random random = new Random();

private final CharacterRepository characterRepository;
private final CharacterMapper mapper;

@Override
public CharacterDto getRandomCharacter() {
int id = random.nextInt(listSize) + 1;
return mapper.toDto(characterRepository.findById((long) id).orElseThrow(
() -> new RuntimeException("Characters not found by id: " + id))
);
}

@Override
public void saveAll(List<CharacterResponseDto> listDto) {
List<Character> characters = listDto.stream()
.map(mapper::toModel)
.toList();
listSize = characters.size();
characterRepository.saveAll(characters);
}

@Override
public List<CharacterDto> findByName(String name) {
return characterRepository.findByNameContaining(name).stream()
.map(mapper::toDto)
.toList();
}
}
10 changes: 10 additions & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
spring.datasource.url=jdbc:mysql://localhost:3306/rick_and_morty?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=Romaxa051979
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it required property? if not should be removed

Suggested change
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect


#spring.jpa.hibernate.ddl-auto=validate
spring.jpa.hibernate.ddl-auto=create-drop
server.servlet.context-path=/api
spring.jpa.show-sql=true
spring.jpa.open-in-view=false
5 changes: 0 additions & 5 deletions src/test/java/mate/academy/rickandmorty/ApplicationTests.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
package mate.academy.rickandmorty;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class ApplicationTests {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

empty class should be removed.

or write the tests.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not fixed


@Test
void contextLoads() {
}

}