diff --git a/application/model/src/main/java/org/fuseri/model/dto/certificate/CertificateDto.java b/application/model/src/main/java/org/fuseri/model/dto/certificate/CertificateDto.java index 52597af3c50c48aa3adc8136f134aaf05b6f35b7..6d55d5774ba75ebd158a05b9541c943bd2dbc4ac 100644 --- a/application/model/src/main/java/org/fuseri/model/dto/certificate/CertificateDto.java +++ b/application/model/src/main/java/org/fuseri/model/dto/certificate/CertificateDto.java @@ -33,6 +33,6 @@ public class CertificateDto extends DomainObjectDto { private CertificateFileDto certificateFile; public CertificateDto() { - setId("0"); + setId(0L); } } diff --git a/application/model/src/main/java/org/fuseri/model/dto/common/DomainObjectDto.java b/application/model/src/main/java/org/fuseri/model/dto/common/DomainObjectDto.java index 2c1aff83f7461224ef599deeadb8426945f7e416..36ec98b086e27e26deb3e31adeed36e66868d3e5 100644 --- a/application/model/src/main/java/org/fuseri/model/dto/common/DomainObjectDto.java +++ b/application/model/src/main/java/org/fuseri/model/dto/common/DomainObjectDto.java @@ -11,5 +11,5 @@ public abstract class DomainObjectDto { @NotBlank @NotNull - private String id; + private Long id; } diff --git a/application/model/src/main/java/org/fuseri/model/dto/course/CourseCreateDto.java b/application/model/src/main/java/org/fuseri/model/dto/course/CourseCreateDto.java index 88995655d12e28abdf75cdd041d93d8d92ff7b8b..64c78eec16aa0a472883f9b1d705d8168d523b8f 100644 --- a/application/model/src/main/java/org/fuseri/model/dto/course/CourseCreateDto.java +++ b/application/model/src/main/java/org/fuseri/model/dto/course/CourseCreateDto.java @@ -28,10 +28,10 @@ public class CourseCreateDto { @NotNull(message = "Language type is required") @Valid - private LanguageTypeDto languageTypeDto; + private LanguageTypeDto language; @NotNull(message = "Proficiency level is required") @Valid - private ProficiencyLevelDto proficiencyLevelDto; + private ProficiencyLevelDto proficiency; } diff --git a/application/model/src/main/java/org/fuseri/model/dto/course/CourseDto.java b/application/model/src/main/java/org/fuseri/model/dto/course/CourseDto.java index 544d06f5da178415352ad7c8c826b0bffc3e0fe9..18e5695b056c1f3f477a05c5abd8f83bba32c9a1 100644 --- a/application/model/src/main/java/org/fuseri/model/dto/course/CourseDto.java +++ b/application/model/src/main/java/org/fuseri/model/dto/course/CourseDto.java @@ -20,7 +20,7 @@ import java.util.List; */ @Getter @Setter -@EqualsAndHashCode +@EqualsAndHashCode(callSuper = true) public class CourseDto extends DomainObjectDto { @NotBlank(message = "Course name is required") @@ -33,22 +33,22 @@ public class CourseDto extends DomainObjectDto { @NotNull(message = "Language type is required") @Valid - private LanguageTypeDto languageTypeDto; + private LanguageTypeDto language; @NotNull(message = "Proficiency level is required") @Valid - private ProficiencyLevelDto proficiencyLevelDto; + private ProficiencyLevelDto proficiency; @NotNull(message = "Student's list is required") @Valid - private List<String> studentIds; + private List<Long> studentIds; - public CourseDto(String name, Integer capacity, LanguageTypeDto languageTypeDto, ProficiencyLevelDto proficiencyLevelDto) { - setId("0"); + public CourseDto(Long id, String name, Integer capacity, LanguageTypeDto languageTypeDto, ProficiencyLevelDto proficiencyLevelDto) { + this.setId(id); this.name = name; this.capacity = capacity; - this.languageTypeDto = languageTypeDto; - this.proficiencyLevelDto = proficiencyLevelDto; + this.language = languageTypeDto; + this.proficiency = proficiencyLevelDto; this.studentIds = new ArrayList<>(); } } diff --git a/application/model/src/main/java/org/fuseri/model/dto/lecture/LectureDto.java b/application/model/src/main/java/org/fuseri/model/dto/lecture/LectureDto.java index df9b17a7c765223d6e7ae8c56593993298c3fa33..f54ac383238e7e6cfbecbde6a71af275f4a4efb0 100644 --- a/application/model/src/main/java/org/fuseri/model/dto/lecture/LectureDto.java +++ b/application/model/src/main/java/org/fuseri/model/dto/lecture/LectureDto.java @@ -36,7 +36,7 @@ public class LectureDto extends DomainObjectDto { private String courseId; @NotNull(message = "Student IDs list cannot be null") - private List<String> studentIds; + private List<Long> studentIds; public LectureDto(LocalDateTime from, LocalDateTime to, String topic, Integer capacity, String lecturerId, String courseId) { this.from = from; diff --git a/application/model/src/main/java/org/fuseri/model/dto/user/UserDto.java b/application/model/src/main/java/org/fuseri/model/dto/user/UserDto.java index fce12aabfb8baadbeb620c531ffcc84a92c4bb77..4d6eba739bf848cf3933c63a8f9ca6607da95b59 100644 --- a/application/model/src/main/java/org/fuseri/model/dto/user/UserDto.java +++ b/application/model/src/main/java/org/fuseri/model/dto/user/UserDto.java @@ -1,10 +1,9 @@ package org.fuseri.model.dto.user; import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import org.fuseri.model.dto.common.DomainObjectDto; import lombok.Getter; import lombok.Setter; +import org.fuseri.model.dto.common.DomainObjectDto; @Getter @Setter @@ -21,7 +20,7 @@ public class UserDto extends DomainObjectDto { public UserDto(String username, String email, String firstName, String lastName, AddressDto address) { - setId("0"); + setId(0L); this.username = username; this.email = email; this.firstName = firstName; diff --git a/application/module-language-school/pom.xml b/application/module-language-school/pom.xml index 42e3a5ded4aed76f99a3ae2be4c55d304e05b0d0..7658592920184dae5c955818294f9a844fc12f71 100644 --- a/application/module-language-school/pom.xml +++ b/application/module-language-school/pom.xml @@ -59,6 +59,10 @@ <version>0.0.1-SNAPSHOT</version> </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-tx</artifactId> + </dependency> </dependencies> diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/common/DomainObject.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/common/DomainObject.java index 8520e8aa4ca12429b526281cce2f466ad735e299..078871d947aaa180bd7a5f6549354cadd7b2eade 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/common/DomainObject.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/common/DomainObject.java @@ -1,18 +1,19 @@ package org.fuseri.modulelanguageschool.common; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.MappedSuperclass; import lombok.Getter; import lombok.Setter; -import java.util.UUID; - @Getter @Setter @MappedSuperclass public abstract class DomainObject { @Id - private String id = UUID.randomUUID().toString(); + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; } diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/common/DomainService.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/common/DomainService.java index 706071fb66c60702f9d1495bbdf2f8e7db533f31..426ef5c3175fe0ac56d823adfdd8d9fda27b7138 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/common/DomainService.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/common/DomainService.java @@ -10,7 +10,7 @@ public abstract class DomainService<T extends DomainObject> { public static final int DEFAULT_PAGE_SIZE = 10; - public abstract JpaRepository<T, String> getRepository(); + public abstract JpaRepository<T, Long> getRepository(); @Transactional public T create(T entity) { diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/common/ResourceNotFoundException.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/common/ResourceNotFoundException.java new file mode 100644 index 0000000000000000000000000000000000000000..2227c5640bba11c5405bc103d2cc4ddbd9f67c8e --- /dev/null +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/common/ResourceNotFoundException.java @@ -0,0 +1,22 @@ +package org.fuseri.modulelanguageschool.common; + +public class ResourceNotFoundException extends RuntimeException { + public ResourceNotFoundException() { + } + + public ResourceNotFoundException(String message) { + super(message); + } + + public ResourceNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public ResourceNotFoundException(Throwable cause) { + super(cause); + } + + public ResourceNotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/Course.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/Course.java index 38f42dfa4b571e5e77cb362df20d89fc73d038ac..455637c7c192242c581e4c1200b261996cac3930 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/Course.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/Course.java @@ -3,11 +3,14 @@ package org.fuseri.modulelanguageschool.course; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; import lombok.*; import org.fuseri.modulelanguageschool.common.DomainObject; @Getter @Setter +@Entity +@Table(name = "course") @NoArgsConstructor @AllArgsConstructor public class Course extends DomainObject { @@ -19,5 +22,5 @@ public class Course extends DomainObject { private Language language; @Enumerated(EnumType.STRING) - private ProficiencyLevel proficiencyLevel; + private ProficiencyLevel proficiency; } diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseController.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseController.java index 9646fb8ff0c88dc974b065f545f17f365c7c0ded..75e92aa7908ae19009769db434bebbb248839fe1 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseController.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseController.java @@ -1,12 +1,15 @@ package org.fuseri.modulelanguageschool.course; import jakarta.validation.Valid; -import jakarta.validation.constraints.PositiveOrZero; import org.fuseri.model.dto.course.CourseCreateDto; import org.fuseri.model.dto.course.CourseDto; import org.fuseri.model.dto.course.LanguageTypeDto; import org.fuseri.model.dto.course.ProficiencyLevelDto; import org.fuseri.model.dto.user.UserDto; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; import org.springframework.web.bind.annotation.*; import java.util.ArrayList; @@ -21,6 +24,12 @@ import java.util.List; public class CourseController { public static final String COURSE_NAME = "english b2 course"; + private final CourseFacade courseFacade; + + @Autowired + public CourseController(CourseFacade courseFacade) { + this.courseFacade = courseFacade; + } /** * Creates a new course. @@ -30,7 +39,7 @@ public class CourseController { */ @PostMapping("/create") public CourseDto create(@Valid @RequestBody CourseCreateDto dto) { - return new CourseDto(dto.getName(), dto.getCapacity(), dto.getLanguageTypeDto(), dto.getProficiencyLevelDto()); + return courseFacade.create(dto); } /** @@ -40,8 +49,8 @@ public class CourseController { * @return the CourseDto for the specified ID */ @GetMapping("/find/{id}") - public CourseDto find(@PathVariable String id) { - return new CourseDto(COURSE_NAME, 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2); + public CourseDto find(@PathVariable Long id) { + return courseFacade.findById(id); } /** @@ -51,8 +60,8 @@ public class CourseController { * @return the Result containing the requested page of CourseDtos */ @GetMapping("/findAll") - public List<CourseDto> findAll(@RequestParam int page) { - return new ArrayList<>(); + public Page<CourseDto> findAll(@RequestParam int page) { + return courseFacade.findAll(PageRequest.of(page, 10, Sort.by(Sort.Direction.ASC, "name"))); } /** @@ -90,18 +99,18 @@ public class CourseController { * @return the updated CourseDto */ @PutMapping("/update/{id}") - public CourseDto update(@PathVariable String id, @Valid @RequestBody CourseCreateDto dto) { - return new CourseDto(dto.getName(), dto.getCapacity(), dto.getLanguageTypeDto(), dto.getProficiencyLevelDto()); + public CourseDto update(@PathVariable Long id, @Valid @RequestBody CourseCreateDto dto) { + return courseFacade.update(id, dto); } /** * Deletes a course by ID. * * @param id the ID of the course to delete - * @return true if the course was successfully deleted, false otherwise */ @DeleteMapping("/delete/{id}") - public void delete(@PathVariable String id) { + public void delete(@PathVariable Long id) { + courseFacade.delete(id); } @@ -113,8 +122,8 @@ public class CourseController { * @return the CourseDto representing the updated course */ @PatchMapping("/enrol/{id}") - public CourseDto enrol(@PathVariable String id, @RequestBody UserDto student) { - var course = new CourseDto(COURSE_NAME, 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2); + public CourseDto enrol(@PathVariable Long id, @RequestBody UserDto student) { + var course = new CourseDto(0L, COURSE_NAME, 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2); course.setStudentIds(new ArrayList<>(List.of(student.getId()))); return course; } @@ -127,8 +136,8 @@ public class CourseController { * @return the CourseDto representing the updated course */ @PatchMapping("/expel/{id}") - public CourseDto expel(@PathVariable String id, @RequestBody UserDto student) { - return new CourseDto(COURSE_NAME, 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2); + public CourseDto expel(@PathVariable Long id, @RequestBody UserDto student) { + return new CourseDto(0L, COURSE_NAME, 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2); } } diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseFacade.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseFacade.java new file mode 100644 index 0000000000000000000000000000000000000000..9899db25414b7d7ef3a6e69384c89f6a365b9ca5 --- /dev/null +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseFacade.java @@ -0,0 +1,49 @@ +package org.fuseri.modulelanguageschool.course; + +import org.fuseri.model.dto.course.CourseCreateDto; +import org.fuseri.model.dto.course.CourseDto; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class CourseFacade { + private final CourseService courseService; + private final CourseMapper courseMapper; + + @Autowired + public CourseFacade(CourseService courseService, CourseMapper courseMapper) { + this.courseService = courseService; + this.courseMapper = courseMapper; + } + + @Transactional + public CourseDto create(CourseCreateDto dto) { + return courseMapper.mapToDto(courseService.save(courseMapper.mapToCourse(dto))); + } + + @Cacheable(cacheNames = "courses", key = "#id") + @Transactional(readOnly = true) + public CourseDto findById(Long id) { + return courseMapper.mapToDto(courseService.findById(id)); + } + + @Transactional(readOnly = true) + public Page<CourseDto> findAll(Pageable pageable) { + return courseMapper.mapToPageDto(courseService.findAll(pageable)); + } + + @Transactional + public CourseDto update(Long id, CourseCreateDto dto) { + return courseMapper.mapToDto(courseService.update(id, courseMapper.mapToCourse(dto))); + } + + @Transactional + public void delete(Long id) { + courseService.delete(id); + } +} diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseMapper.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..9a5bf7c032fb11df53ef65ddad42b0e82230a7bf --- /dev/null +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseMapper.java @@ -0,0 +1,27 @@ +package org.fuseri.modulelanguageschool.course; + +import org.fuseri.model.dto.course.CourseCreateDto; +import org.fuseri.model.dto.course.CourseDto; +import org.mapstruct.Mapper; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; + +import java.util.List; + +@Mapper(componentModel = "spring") +public interface CourseMapper { + + CourseDto mapToDto(Course course); + + Course mapToCourse(CourseDto courseDto); + + List<CourseDto> mapToList(List<Course> persons); + + + default Page<CourseDto> mapToPageDto(Page<Course> courses) { + return new PageImpl<>(mapToList(courses.getContent()), courses.getPageable(), courses.getTotalPages()); + } + + Course mapToCourse(CourseCreateDto dto); +} + diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseRepository.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..1dcad4467b891675816f8b3f58e82b5b92766a31 --- /dev/null +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseRepository.java @@ -0,0 +1,9 @@ +package org.fuseri.modulelanguageschool.course; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CourseRepository extends JpaRepository<Course, Long> { + +} diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseService.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseService.java new file mode 100644 index 0000000000000000000000000000000000000000..eb20658504ff81a3fa342dcd0ed88037da2329df --- /dev/null +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/CourseService.java @@ -0,0 +1,57 @@ +package org.fuseri.modulelanguageschool.course; + +import org.fuseri.modulelanguageschool.common.ResourceNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; + +@Service +public class CourseService { + + private final CourseRepository courseRepository; + + @Autowired + public CourseService(CourseRepository courseRepository) { + this.courseRepository = courseRepository; + } + + @Transactional + public Course save(Course course) { + return courseRepository.save(course); + } + + @Transactional(readOnly = true) + public Course findById(Long id) { + return courseRepository.findById(id) + .orElseThrow(() -> new ResourceNotFoundException("Course with id: " + id + " was not found.")); + } + + @Transactional(readOnly = true) + public Page<Course> findAll(Pageable pageable) { + return courseRepository.findAll(pageable); + } + + @Transactional + public Course update(Long id, Course newCourse) { + Optional<Course> optionalCourse = courseRepository.findById(id); + if (optionalCourse.isPresent()) { + Course course = optionalCourse.get(); + course.setName(newCourse.getName()); + course.setCapacity(newCourse.getCapacity()); + course.setLanguage(newCourse.getLanguage()); + course.setProficiency(newCourse.getProficiency()); + return courseRepository.save(course); + } else { + throw new ResourceNotFoundException("Course with id: " + id + " was not found."); + } + } + + @Transactional + public void delete(Long id) { + courseRepository.deleteById(id); + } +} diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/UserController.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/UserController.java index d0c6429b245ad650d6e5fe747d9db2fb48e88681..6164c8e6be3fdbcf84f20b1ccd0cedded92c9f5a 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/UserController.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/UserController.java @@ -25,13 +25,13 @@ public class UserController { private final UserMapper mapper; @Autowired - public UserController(UserService service/*, UserMapper mapper*/) { + public UserController(UserService service, UserMapper mapper) { this.service = service; - this.mapper = null; + this.mapper = mapper; } @GetMapping("/{id}") - public UserDto find(@PathVariable String id) { + public UserDto find(@PathVariable Long id) { return new UserDto("spracher","spracher@gmail.com","Sprach","MeNot",new AddressDto()); } @@ -41,12 +41,12 @@ public class UserController { } @DeleteMapping("/{id}") - public UserDto deleteUser(@PathVariable String id) { + public UserDto deleteUser(@PathVariable Long id) { return new UserDto("spracher","spracher@gmail.com","Sprach","MeNot",new AddressDto()); } @PutMapping("/update/{id}") - public UserDto update(@PositiveOrZero @PathVariable String id,@Valid @RequestBody UserCreateDto user) { + public UserDto update(@PositiveOrZero @PathVariable Long id,@Valid @RequestBody UserCreateDto user) { return new UserDto(user.getUsername(),user.getEmail(),user.getFirstName(),user.getLastName(),user.getAddress()); } @@ -68,22 +68,22 @@ public class UserController { @PostMapping("/logout/{id}") - public String logout(@PathVariable String id) { + public String logout(@PathVariable Long id) { return "user has logged out"; } @GetMapping("/finished/{id}") - public List<Course> getFinished(@PathVariable String id) { + public List<Course> getFinished(@PathVariable Long id) { return new ArrayList<>(); } @GetMapping("/enrolled/{id}") - public List<Course> getEnrolled(@PathVariable String id) { + public List<Course> getEnrolled(@PathVariable Long id) { return new ArrayList<>(); } @PutMapping("/addLanguage/{id}") - public String addLanguage(@PathVariable String id,@Valid @RequestBody UserAddLanguageDto body) { + public String addLanguage(@PathVariable Long id,@Valid @RequestBody UserAddLanguageDto body) { return "added Absolutely Nothing successfully!"; } diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/UserRepository.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/UserRepository.java index 32d06b1313423619b849410606b36283efa90802..f649fbd47a04403b2e6996893d640a84449f7602 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/UserRepository.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/UserRepository.java @@ -4,5 +4,5 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository -public interface UserRepository extends JpaRepository<User, String> { +public interface UserRepository extends JpaRepository<User, Long> { } diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/UserService.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/UserService.java index 1fc03b8ca97b71263d0b3c2f962cb275890af690..12853d56cb04e9d7c550cfff22814878f1e1cddc 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/UserService.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/UserService.java @@ -19,7 +19,7 @@ public class UserService extends DomainService<User> { } @Transactional(readOnly = true) - public User find(String id) { + public User find(Long id) { return repository.findById(id) .orElseThrow(() -> new EntityNotFoundException("User '" + id + "' not found.")); } diff --git a/application/module-language-school/src/main/resources/application.properties b/application/module-language-school/src/main/resources/application.properties index 888dcec44dfa5c7cece2f03962df19175a89349e..08d8fcc59c97de1773876715a96a126e0831521e 100644 --- a/application/module-language-school/src/main/resources/application.properties +++ b/application/module-language-school/src/main/resources/application.properties @@ -1 +1,13 @@ -server.port=5000 \ No newline at end of file +server.port=5000 + +spring.jpa.open-in-view=false +spring.datasource.url=jdbc:h2:mem:social-network;MODE=PostgreSQL +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=SedaQ-app +spring.datasource.password=$argon2id$v=19$m=16,t=2,p=1$YmF0bWFuYmF0bWFu$MdHYB359HdivAb9J6CaILw +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect +# showing SQL is generally good practice for running project locally to check whether there is not an issue with implementation of JPA methods. +spring.jpa.show-sql=true +spring.jackson.property-naming-strategy=LOWER_CAMEL_CASE +spring.cache.type=NONE +appconfig.enablecache=false \ No newline at end of file diff --git a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseTest.java b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseTest.java index e4fd8f0e5c56d80e54d57c39780620ed4aa07407..05add7ac41aec771688261bfdeebe2d113c013a2 100644 --- a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseTest.java +++ b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/course/CourseTest.java @@ -14,6 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.data.domain.PageImpl; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; @@ -21,7 +22,8 @@ import java.util.ArrayList; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -29,15 +31,24 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @SpringBootTest @AutoConfigureMockMvc public class CourseTest { + + private final CourseCreateDto courseCreateDto = new CourseCreateDto("english b2 course", 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2); + private final CourseDto courseDto = new CourseDto(0L, "english b2 course", 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2); @Autowired ObjectMapper objectMapper; @Autowired private MockMvc mockMvc; + @MockBean private CourseController courseController; - private final CourseCreateDto courseCreateDto = new CourseCreateDto("english b2 course", 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2);; - private final CourseDto courseDto = new CourseDto("english b2 course", 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2); + public static String asJsonString(final Object obj) { + try { + return new ObjectMapper().writeValueAsString(obj); + } catch (Exception e) { + throw new RuntimeException(e); + } + } @Test void createCourse() throws Exception { @@ -48,8 +59,8 @@ public class CourseTest { .andExpect(status().isOk()) .andExpect(jsonPath("$.name").value("english b2 course")) .andExpect(jsonPath("$.capacity").value(10)) - .andExpect(jsonPath("$.languageTypeDto").value("ENGLISH")) - .andExpect(jsonPath("$.proficiencyLevelDto").value("B2")) + .andExpect(jsonPath("$.language").value("ENGLISH")) + .andExpect(jsonPath("$.proficiency").value("B2")) .andExpect(jsonPath("$.id").exists()) .andReturn().getResponse().getContentAsString(); } @@ -74,21 +85,21 @@ public class CourseTest { @Test void findCourse() throws Exception { - String id = "0"; + Long id = 0L; Mockito.when(courseController.find(id)).thenReturn(courseDto); mockMvc.perform(get("/courses/find/" + id)) .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(id)) .andExpect(jsonPath("$.name").value("english b2 course")) .andExpect(jsonPath("$.capacity").value(10)) - .andExpect(jsonPath("$.languageTypeDto").value("ENGLISH")) - .andExpect(jsonPath("$.proficiencyLevelDto").value("B2")) - .andExpect(jsonPath("$.id").value(id)) + .andExpect(jsonPath("$.language").value("ENGLISH")) + .andExpect(jsonPath("$.proficiency").value("B2")) .andReturn().getResponse().getContentAsString(); } @Test void findCourseWithoutId() throws Exception { - Mockito.when(courseController.find(ArgumentMatchers.anyString())).thenReturn(courseDto); + Mockito.when(courseController.find(ArgumentMatchers.anyLong())).thenReturn(courseDto); mockMvc.perform(get("/courses/find/")) .andExpect(status().is4xxClientError()); } @@ -96,18 +107,18 @@ public class CourseTest { @Test void findAll() throws Exception { int page = 0; - Mockito.when(courseController.findAll(page)).thenReturn(new ArrayList<>()); + Mockito.when(courseController.findAll(page)).thenReturn(new PageImpl<>(new ArrayList<>())); String response = mockMvc.perform(get("/courses/findAll").param("page", Integer.toString(page))) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(); - assertThat("response", response, is("[]")); + assertTrue(response.contains("\"content\":[]")); } @Test void findAllWithoutPage() throws Exception { - Mockito.when(courseController.findAll(ArgumentMatchers.anyInt())).thenReturn(new ArrayList<>()); - mockMvc.perform(get("/courses/findAll")) +// Mockito.when(courseController.findAll(ArgumentMatchers.anyInt())).thenReturn(new PageImpl<>(new ArrayList<>())); + mockMvc.perform(get("/courses/findAll")) .andExpect(status().is4xxClientError()); } @@ -128,7 +139,7 @@ public class CourseTest { @Test void findAllByLangWithoutParameters() throws Exception { Mockito.when(courseController.findAll(ArgumentMatchers.anyInt(), - ArgumentMatchers.isA(LanguageTypeDto.class))) + ArgumentMatchers.isA(LanguageTypeDto.class))) .thenReturn(new ArrayList<>()); mockMvc.perform(get("/courses/findAllByLang")) .andExpect(status().is4xxClientError()); @@ -138,7 +149,7 @@ public class CourseTest { void findAllByLangWithoutLang() throws Exception { Mockito.when(courseController.findAll(ArgumentMatchers.anyInt(), ArgumentMatchers.isA(LanguageTypeDto.class))) - .thenReturn(new ArrayList<>()); + .thenReturn(new ArrayList<>()); String page = "0"; mockMvc.perform(get("/courses/findAllByLang").param("page", page)) .andExpect(status().is4xxClientError()); @@ -183,26 +194,26 @@ public class CourseTest { @Test void updateCourse() throws Exception { - String id = "0"; + Long id = 0L; Mockito.when(courseController.update(ArgumentMatchers.eq(id), - ArgumentMatchers.isA(CourseCreateDto.class))) + ArgumentMatchers.isA(CourseCreateDto.class))) .thenReturn(courseDto); mockMvc.perform(put("/courses/update/" + id) - .content(asJsonString(courseDto)) - .contentType(MediaType.APPLICATION_JSON)) + .content(asJsonString(courseDto)) + .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.name").value("english b2 course")) .andExpect(jsonPath("$.capacity").value(10)) - .andExpect(jsonPath("$.languageTypeDto").value("ENGLISH")) - .andExpect(jsonPath("$.proficiencyLevelDto").value("B2")) + .andExpect(jsonPath("$.language").value("ENGLISH")) + .andExpect(jsonPath("$.proficiency").value("B2")) .andExpect(jsonPath("$.id").value(courseDto.getId())) .andReturn().getResponse().getContentAsString(); } @Test void updateCourseWithoutParameter() throws Exception { - Mockito.when(courseController.update(ArgumentMatchers.anyString(), + Mockito.when(courseController.update(ArgumentMatchers.anyLong(), ArgumentMatchers.isA(CourseCreateDto.class))) .thenReturn(courseDto); mockMvc.perform(put("/courses/update")) @@ -211,7 +222,7 @@ public class CourseTest { @Test void deleteCourse() throws Exception { - String id = "0"; + Long id = 0L; Mockito.doNothing().when(courseController).delete(id); mockMvc.perform(delete("/courses/delete/" + id)) @@ -220,7 +231,7 @@ public class CourseTest { @Test void deleteCourseWithoutParameter() throws Exception { - Mockito.doNothing().when(courseController).delete(ArgumentMatchers.anyString()); + Mockito.doNothing().when(courseController).delete(ArgumentMatchers.anyLong()); mockMvc.perform(delete("/courses/delete/")) .andExpect(status().is4xxClientError()); @@ -228,11 +239,11 @@ public class CourseTest { @Test void enrolCourse() throws Exception { - String id = "0"; - UserDto student = new UserDto("novakovat","novakova@gamil.com", "Tereza", + Long id = 0L; + UserDto student = new UserDto("novakovat", "novakova@gamil.com", "Tereza", "Nováková", new AddressDto()); - CourseDto courseDtoWithStudent = new CourseDto("english b2 course", 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2); + CourseDto courseDtoWithStudent = new CourseDto(id, "english b2 course", 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2); courseDtoWithStudent.setStudentIds(new ArrayList<>(List.of(student.getId()))); Mockito.when(courseController.enrol(ArgumentMatchers.eq(id), @@ -244,16 +255,16 @@ public class CourseTest { .andExpect(status().isOk()) .andExpect(jsonPath("$.name").value("english b2 course")) .andExpect(jsonPath("$.capacity").value(10)) - .andExpect(jsonPath("$.languageTypeDto").value("ENGLISH")) - .andExpect(jsonPath("$.proficiencyLevelDto").value("B2")) - .andExpect(jsonPath("$.studentIds").value(student.getId())) + .andExpect(jsonPath("$.language").value("ENGLISH")) + .andExpect(jsonPath("$.proficiency").value("B2")) + .andExpect(jsonPath("$.studentIds").exists()) .andReturn().getResponse().getContentAsString(); } @Test void enrolCourseWithoutUserParameter() throws Exception { String id = "0"; - Mockito.when(courseController.enrol(ArgumentMatchers.anyString(), + Mockito.when(courseController.enrol(ArgumentMatchers.anyLong(), ArgumentMatchers.isA(UserDto.class))) .thenReturn(courseDto); mockMvc.perform(patch("/courses/enrol/" + id)) @@ -262,26 +273,26 @@ public class CourseTest { @Test void enrolCourseWithoutCourseIdParameter() throws Exception { - Mockito.when(courseController.enrol(ArgumentMatchers.anyString(), + Mockito.when(courseController.enrol(ArgumentMatchers.anyLong(), ArgumentMatchers.isA(UserDto.class))) .thenReturn(courseDto); - UserDto student = new UserDto("novakovat","novakova@gamil.com", "Tereza", + UserDto student = new UserDto("novakovat", "novakova@gamil.com", "Tereza", "Nováková", new AddressDto()); mockMvc.perform(patch("/courses/enrol/") - .content(asJsonString(student)) - .contentType(MediaType.APPLICATION_JSON)) + .content(asJsonString(student)) + .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().is4xxClientError()); } @Test void expelCourse() throws Exception { - String id = "0"; + Long id = 0L; Mockito.when(courseController.expel(ArgumentMatchers.eq(id), ArgumentMatchers.isA(UserDto.class))) .thenReturn(courseDto); - UserDto student = new UserDto("novakovat","novakova@gamil.com", "Tereza", + UserDto student = new UserDto("novakovat", "novakova@gamil.com", "Tereza", "Nováková", new AddressDto()); mockMvc.perform(patch("/courses/expel/" + id) @@ -290,15 +301,15 @@ public class CourseTest { .andExpect(status().isOk()) .andExpect(jsonPath("$.name").value("english b2 course")) .andExpect(jsonPath("$.capacity").value(10)) - .andExpect(jsonPath("$.languageTypeDto").value("ENGLISH")) - .andExpect(jsonPath("$.proficiencyLevelDto").value("B2")) + .andExpect(jsonPath("$.language").value("ENGLISH")) + .andExpect(jsonPath("$.proficiency").value("B2")) .andExpect(jsonPath("$.studentIds").isEmpty()) .andReturn().getResponse().getContentAsString(); } @Test void expelCourseWithoutUserParameter() throws Exception { - String id = "0"; + Long id = 0L; Mockito.when(courseController.expel(ArgumentMatchers.eq(id), ArgumentMatchers.isA(UserDto.class))) .thenReturn(courseDto); @@ -309,10 +320,10 @@ public class CourseTest { @Test void deleteCourseWithoutCourseIdParameter() throws Exception { - Mockito.when(courseController.expel(ArgumentMatchers.anyString(), + Mockito.when(courseController.expel(ArgumentMatchers.anyLong(), ArgumentMatchers.isA(UserDto.class))) .thenReturn(courseDto); - UserDto student = new UserDto("novakovat","novakova@gamil.com", "Tereza", + UserDto student = new UserDto("novakovat", "novakova@gamil.com", "Tereza", "Nováková", new AddressDto()); mockMvc.perform(patch("/courses/expel/") @@ -320,12 +331,4 @@ public class CourseTest { .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().is4xxClientError()); } - - public static String asJsonString(final Object obj) { - try { - return new ObjectMapper().writeValueAsString(obj); - } catch (Exception e) { - throw new RuntimeException(e); - } - } } diff --git a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/user/UserControllerTest.java b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/user/UserControllerTest.java index 85aa5f33c134528abba0f729717a020278e440bb..59f5032bf8a1fe520fa1160415230843c3d2850f 100644 --- a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/user/UserControllerTest.java +++ b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/user/UserControllerTest.java @@ -121,7 +121,7 @@ class UserControllerTest { .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); - String id = objectMapper.readValue(response, UserDto.class).getId(); + Long id = objectMapper.readValue(response, UserDto.class).getId(); mockMvc.perform(get("/users/{id}", id)) .andExpect(status().isOk()) @@ -142,7 +142,7 @@ class UserControllerTest { .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); - String id = objectMapper.readValue(response, UserDto.class).getId(); + Long id = objectMapper.readValue(response, UserDto.class).getId(); mockMvc.perform(delete("/users/{id}", id) .contentType(MediaType.APPLICATION_JSON)) @@ -156,7 +156,7 @@ class UserControllerTest { .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); - String id = objectMapper.readValue(response, UserDto.class).getId(); + Long id = objectMapper.readValue(response, UserDto.class).getId(); var updatedUsername = "novak"; var userToUpdate = new UserCreateDto( @@ -195,7 +195,7 @@ class UserControllerTest { .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); - String id = objectMapper.readValue(response, UserDto.class).getId(); + Long id = objectMapper.readValue(response, UserDto.class).getId(); mockMvc.perform(post("/users/logout/{id}", id)) .andExpect(status().isOk()); @@ -203,19 +203,19 @@ class UserControllerTest { @Test void getFinished() throws Exception { - mockMvc.perform(get("/users/finished/{id}", "1c1bbf66-6585-4978-886b-b126335ff3af")) + mockMvc.perform(get("/users/finished/1", "1c1bbf66-6585-4978-886b-b126335ff3af")) .andExpect(status().isOk()); } @Test void getEnrolled() throws Exception { - mockMvc.perform(get("/users/enrolled/{id}", "1c1bbf66-6585-4978-886b-b126335ff3af")) + mockMvc.perform(get("/users/enrolled/1", "1c1bbf66-6585-4978-886b-b126335ff3af")) .andExpect(status().isOk()); } @Test void addLanguage() throws Exception { - mockMvc.perform(put("/users/addLanguage/{id}", "1c1bbf66-6585-4978-886b-b126335ff3af") + mockMvc.perform(put("/users/addLanguage/1", "1c1bbf66-6585-4978-886b-b126335ff3af") .content(asJsonString(new UserAddLanguageDto(LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2))) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); diff --git a/application/module-language-school/src/test/resources/application-test.properties b/application/module-language-school/src/test/resources/application-test.properties new file mode 100644 index 0000000000000000000000000000000000000000..896213ef130ffc73d291c5d76336ccf6aaef4f9f --- /dev/null +++ b/application/module-language-school/src/test/resources/application-test.properties @@ -0,0 +1,14 @@ +# For description of each field check: https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html +# INIT=CREATE SCHEMA IF NOT EXISTS PA165;SET SCHEMA PA165 +spring.datasource.url=jdbc:h2:mem:testdb;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE +spring.datasource.username=SedaQ-app-test +spring.datasource.password= +spring.datasource.driverClassName=org.h2.Driver +spring.jpa.hibernate.ddl-auto=create +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect +spring.jpa.properties.hibernate.generate_statistics=true +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.properties.hibernate.show_sql=false +spring.h2.console.enabled=true +spring.cache.type=NONE +appconfig.enablecache=false \ No newline at end of file diff --git a/application/module-language-school/src/test/resources/logback.xml b/application/module-language-school/src/test/resources/logback.xml new file mode 100644 index 0000000000000000000000000000000000000000..e449f9cd302a0db94a3f6d8469468a7b277ca638 --- /dev/null +++ b/application/module-language-school/src/test/resources/logback.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration> + + <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>%d %5p %40.40c:%4L - %m%n</pattern> + </encoder> + </appender> + + <root level="info"> + <appender-ref ref="console" /> + </root> +<!-- TODO remove solution--> + <logger name="org.hibernate.SQL" level="DEBUG"/> + +</configuration> \ No newline at end of file