Lab4 in progress

This commit is contained in:
Katerina881 2023-03-21 10:21:00 +04:00
parent 2096215195
commit cbf4b0b9a3
20 changed files with 344 additions and 101 deletions

View File

@ -18,6 +18,7 @@ dependencies {
implementation 'com.h2database:h2:2.1.210'
implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.6.5'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.hibernate.validator:hibernate-validator'
}
tasks.named('test') {

View File

@ -0,0 +1,35 @@
package np.something.DTO;
import np.something.model.Comment;
import np.something.model.Customer;
import np.something.model.Post;
public class CommentDto {
public final long id;
public final String content;
public final Customer customer;
public final Post post;
public CommentDto(Comment comment) {
this.id = comment.getId();
this.content = comment.getContent();
this.customer = comment.getCustomer();
this.post = comment.getPost();
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
public Customer getCustomer() {
return customer;
}
public Post getPost() {
return post;
}
}

View File

@ -0,0 +1,43 @@
package np.something.DTO;
import np.something.model.Comment;
import np.something.model.Customer;
import np.something.model.Post;
import java.util.List;
public class CustomerDto {
public final long id;
public final String username;
public final String hashedPassword;
public final List<Comment> comments;
public final List<Post> posts;
public CustomerDto(Customer customer) {
this.id = customer.getId();
this.username = customer.getUsername();
this.hashedPassword = customer.getPassword();
this.comments = customer.getComments();
this.posts = customer.getPosts();
}
public long getId() {
return id;
}
public String getUsername() {
return username;
}
public String getHashedPassword() {
return hashedPassword;
}
public List<Comment> getComments() {
return comments;
}
public List<Post> getPosts() {
return posts;
}
}

View File

@ -0,0 +1,43 @@
package np.something.DTO;
import np.something.model.Comment;
import np.something.model.Customer;
import np.something.model.Post;
import java.util.List;
public class PostDto {
public final long id;
public final String title;
public final String content;
public final Customer customer;
public final List<Comment> comments;
public PostDto(Post post) {
this.id = post.getId();
this.title = post.getTitle();
this.content = post.getContent();
this.customer = post.getCustomer();
this.comments = post.getComments();
}
public long getId() {
return id;
}
public String getTitle() {
return title;
}
public String getContent() {
return content;
}
public Customer getCustomer() {
return customer;
}
public List<Comment> getComments() {
return comments;
}
}

View File

@ -0,0 +1,7 @@
package np.something.Exceptions;
public class CommentNotFoundException extends RuntimeException {
public CommentNotFoundException(Long id) {
super(String.format("Comment with id [%s] is not found", id));
}
}

View File

@ -0,0 +1,7 @@
package np.something.Exceptions;
public class CustomerNotFoundException extends RuntimeException {
public CustomerNotFoundException(Long id) {
super(String.format("Customer with id [%s] is not found", id));
}
}

View File

@ -0,0 +1,7 @@
package np.something.Exceptions;
public class PostNotFoundException extends RuntimeException {
public PostNotFoundException(Long id) {
super(String.format("Post with id [%s] is not found", id));
}
}

View File

@ -1,6 +1,7 @@
package np.something.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import java.util.Objects;
@ -11,6 +12,7 @@ public class Comment {
private Long id;
@Column
@NotBlank(message = "Content cannot be empty")
private String content;
@ManyToOne(fetch = FetchType.EAGER)

View File

@ -1,6 +1,7 @@
package np.something.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import java.util.*;
@ -10,9 +11,11 @@ public class Customer {
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
@NotBlank(message = "Username cannot be empty")
private String username;
@Column
private String hashedPassword;
@NotBlank(message = "Password cannot be empty")
private String password;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "customer", cascade = CascadeType.ALL)
private List<Comment> comments;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "customer", cascade = CascadeType.ALL)
@ -22,9 +25,9 @@ public class Customer {
}
public Customer(String username, String hashedPassword) {
public Customer(String username, String password) {
this.username = username;
this.hashedPassword = hashedPassword;
this.password = password;
this.comments = new ArrayList<>();
this.posts = new ArrayList<>();
}
@ -37,8 +40,8 @@ public class Customer {
return username;
}
public String getHashedPassword() {
return hashedPassword;
public String getPassword() {
return password;
}
public List<Comment> getComments() {
@ -53,8 +56,8 @@ public class Customer {
this.username = username;
}
public void setHashedPassword(String hashedPassword) {
this.hashedPassword = hashedPassword;
public void setPassword(String password) {
this.password = password;
}
@Override

View File

@ -1,6 +1,7 @@
package np.something.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.List;
@ -12,9 +13,11 @@ public class Post {
private Long id;
@Column
@NotBlank(message = "Title cannot be empty")
private String title;
@Column
@NotBlank(message = "Content cannot be empty")
private String content;
@ManyToOne(fetch = FetchType.EAGER)

View File

@ -0,0 +1,7 @@
package np.something.repositories;
import np.something.model.Comment;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CommentRepository extends JpaRepository<Comment, Long> {
}

View File

@ -0,0 +1,7 @@
package np.something.repositories;
import np.something.model.Customer;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CustomerRepository extends JpaRepository<Customer, Long> {
}

View File

@ -0,0 +1,7 @@
package np.something.repositories;
import np.something.model.Post;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PostRepository extends JpaRepository<Post, Long> {
}

View File

@ -1,72 +1,67 @@
package np.something.services;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.PersistenceContext;
import jakarta.transaction.Transactional;
import np.something.Exceptions.CommentNotFoundException;
import org.springframework.transaction.annotation.Transactional;
import np.something.model.Comment;
import np.something.model.Customer;
import np.something.model.Post;
import np.something.repositories.CommentRepository;
import np.something.util.validation.ValidatorUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Optional;
@Service
public class CommentService {
@PersistenceContext
private EntityManager em;
private final CommentRepository commentRepository;
private final ValidatorUtil validatorUtil;
@Transactional
public Comment findComment(Long id) {
final Comment comment = em.find(Comment.class, id);
if (comment == null) {
throw new EntityNotFoundException(String.format("Comment with id [%s] is not found", id));
}
return comment;
public CommentService(CommentRepository commentRepository,
ValidatorUtil validatorUtil) {
this.commentRepository = commentRepository;
this.validatorUtil = validatorUtil;
}
@Transactional
@Transactional(readOnly = true)
public Comment findComment(Long id) {
final Optional<Comment> comment = commentRepository.findById(id);
return comment.orElseThrow(() -> new CommentNotFoundException(id));
}
@Transactional(readOnly = true)
public List<Comment> findAllComments() {
return em.createQuery("select c from Comment c", Comment.class).getResultList();
return commentRepository.findAll();
}
@Transactional
public Comment addComment(Customer customer, Post post, String content) {
if (customer == null || post == null) {
throw new IllegalArgumentException("Invalid customer or post");
}
if (!StringUtils.hasText(content)) {
throw new IllegalArgumentException("Invalid comment's content");
}
final Comment comment = new Comment(customer, post, content);
comment.getCustomer().getComments().add(comment);
comment.getPost().getComments().add(comment);
em.persist(comment);
return comment;
validatorUtil.validate(comment);
customer.getComments().add(comment);
post.getComments().add(comment);
return commentRepository.save(comment);
}
@Transactional
public Comment updateComment(Long id, String content) {
if (!StringUtils.hasText(content)) {
throw new IllegalArgumentException("Comment's content is empty");
}
final Comment comment = findComment(id);
comment.setContent(content);
return em.merge(comment);
final Comment currentComment = findComment(id);
currentComment.setContent(content);
validatorUtil.validate(currentComment);
return commentRepository.save(currentComment);
}
@Transactional
public Comment deleteComment(Long id) {
final Comment currentComment = findComment(id);
commentRepository.delete(currentComment);
currentComment.getPost().getComments().remove(currentComment);
currentComment.getCustomer().getComments().remove(currentComment);
em.remove(currentComment);
return currentComment;
}
@Transactional
public void deleteAllComment() {
em.createQuery("delete from Comment").executeUpdate();
public void deleteAllComments() {
commentRepository.deleteAll();
}
}

View File

@ -4,7 +4,11 @@ import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.PersistenceContext;
import jakarta.transaction.Transactional;
import np.something.Exceptions.CustomerNotFoundException;
import np.something.model.Customer;
import np.something.repositories.CommentRepository;
import np.something.repositories.CustomerRepository;
import np.something.util.validation.ValidatorUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@ -12,53 +16,50 @@ import java.util.List;
@Service
public class CustomerService {
@PersistenceContext
private EntityManager em;
private final CustomerRepository customerRepository;
private final ValidatorUtil validatorUtil;
public CustomerService(CustomerRepository customerRepository,
ValidatorUtil validatorUtil) {
this.customerRepository = customerRepository;
this.validatorUtil = validatorUtil;
}
@Transactional
public Customer findCustomer(Long id) {
final Customer customer = em.find(Customer.class, id);
if (customer == null) {
throw new EntityNotFoundException(String.format("User with id [%s] is not found", id));
}
return customer;
return customerRepository.findById(id).orElseThrow(() -> new CustomerNotFoundException(id));
}
@Transactional
public List<Customer> findAllCustomers() {
return em.createQuery("select c from Customer c", Customer.class).getResultList();
return customerRepository.findAll();
}
@Transactional
public Customer addCustomer(String username, String password) {
if (!StringUtils.hasText(username) || !StringUtils.hasText(password)) {
throw new IllegalArgumentException("Customer's username or password is empty");
}
final Customer customer = new Customer(username, password);
em.persist(customer);
return customer;
Customer customer = new Customer(username, password);
validatorUtil.validate(customer);
return customerRepository.save(customer);
}
@Transactional
public Customer updateCustomer(Long id, String username, String password) {
if (!StringUtils.hasText(username) || !StringUtils.hasText(password)) {
throw new IllegalArgumentException("Customer's username or password is empty");
}
final Customer customer = findCustomer(id);
Customer customer = findCustomer(id);
customer.setUsername(username);
customer.setHashedPassword(password);
return em.merge(customer);
customer.setPassword(password);
validatorUtil.validate(customer);
return customerRepository.save(customer);
}
@Transactional
public Customer deleteCustomer(Long id) {
final Customer currentCustomer = findCustomer(id);
em.remove(currentCustomer);
return currentCustomer;
Customer customer = findCustomer(id);
customerRepository.delete(customer);
return customer;
}
@Transactional
public void deleteAllCustomers() {
em.createQuery("delete from Customer").executeUpdate();
customerRepository.deleteAll();
}
}

View File

@ -4,9 +4,13 @@ import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.PersistenceContext;
import jakarta.transaction.Transactional;
import np.something.Exceptions.PostNotFoundException;
import np.something.model.Comment;
import np.something.model.Customer;
import np.something.model.Post;
import np.something.repositories.CustomerRepository;
import np.something.repositories.PostRepository;
import np.something.util.validation.ValidatorUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@ -14,58 +18,52 @@ import java.util.List;
@Service
public class PostService {
@PersistenceContext
private EntityManager em;
private final PostRepository postRepository;
private final ValidatorUtil validatorUtil;
public PostService(PostRepository postRepository,
ValidatorUtil validatorUtil) {
this.postRepository = postRepository;
this.validatorUtil = validatorUtil;
}
@Transactional
public Post findPost(Long id) {
final Post post = em.find(Post.class, id);
if (post == null) {
throw new EntityNotFoundException(String.format("Post with id [%s] is not found", id));
}
return post;
return postRepository.findById(id).orElseThrow(() -> new PostNotFoundException(id));
}
@Transactional
public List<Post> findAllPosts() {
return em.createQuery("select p from Post p", Post.class).getResultList();
return postRepository.findAll();
}
@Transactional
public Post addPost(Customer customer, String title, String content) {
if (customer == null) {
throw new IllegalArgumentException("Invalid customer");
}
if (!StringUtils.hasText(title) | !StringUtils.hasText(content)) {
throw new IllegalArgumentException("Invalid post's content or title");
}
final Post post = new Post(customer, title, content);
post.getCustomer().getPosts().add(post);
em.persist(post);
return post;
Post post = new Post(customer, title, content);
validatorUtil.validate(post);
customer.getPosts().add(post);
return postRepository.save(post);
}
@Transactional
public Post updatePost(Long id, String title, String content) {
if (!StringUtils.hasText(content) | !StringUtils.hasText(title)) {
throw new IllegalArgumentException("Post's content or title is empty");
}
final Post post = findPost(id);
Post post = findPost(id);
post.setTitle(title);
post.setContent(content);
return em.merge(post);
validatorUtil.validate(post);
return postRepository.save(post);
}
@Transactional
public Post deletePost(Long id) {
final Post currentPost = findPost(id);
currentPost.getCustomer().getPosts().remove(currentPost);
em.remove(currentPost);
return currentPost;
Post post = findPost(id);
post.getCustomer().getPosts().remove(post);
postRepository.delete(post);
return post;
}
@Transactional
public void deleteAllPosts() {
em.createQuery("delete from Post").executeUpdate();
postRepository.deleteAll();
}
}

View File

@ -0,0 +1,38 @@
package np.something.util.error;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import ru.ulstu.is.sbapp.student.service.StudentNotFoundException;
import ru.ulstu.is.sbapp.util.validation.ValidationException;
import java.util.stream.Collectors;
@ControllerAdvice
public class AdviceController {
@ExceptionHandler({
StudentNotFoundException.class,
ValidationException.class
})
public ResponseEntity<Object> handleException(Throwable e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Object> handleBindException(MethodArgumentNotValidException e) {
final ValidationException validationException = new ValidationException(
e.getBindingResult().getAllErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.toSet()));
return handleException(validationException);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleUnknownException(Throwable e) {
e.printStackTrace();
return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}

View File

@ -0,0 +1,9 @@
package np.something.util.validation;
import java.util.Set;
public class ValidationException extends RuntimeException {
public ValidationException(Set<String> errors) {
super(String.join("\n", errors));
}
}

View File

@ -0,0 +1,30 @@
package np.something.util.validation;
import org.springframework.stereotype.Component;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Set;
import java.util.stream.Collectors;
@Component
public class ValidatorUtil {
private final Validator validator;
public ValidatorUtil() {
try (ValidatorFactory factory = Validation.buildDefaultValidatorFactory()) {
this.validator = factory.getValidator();
}
}
public <T> void validate(T object) {
final Set<ConstraintViolation<T>> errors = validator.validate(object);
if (!errors.isEmpty()) {
throw new ValidationException(errors.stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.toSet()));
}
}
}

View File

@ -22,7 +22,7 @@ public class SocialNetworkTest {
@Test
void testCustomers() {
commentService.deleteAllComment();
commentService.deleteAllComments();
postService.deleteAllPosts();
customerService.deleteAllCustomers();
@ -43,16 +43,16 @@ public class SocialNetworkTest {
Customer c4 = customerService.updateCustomer(c3.getId(), "fourth", "4");
Assertions.assertNotEquals(c3.getUsername(), c4.getUsername());
Assertions.assertNotEquals(c3.getHashedPassword(), c4.getHashedPassword());
Assertions.assertNotEquals(c3.getPassword(), c4.getPassword());
commentService.deleteAllComment();
commentService.deleteAllComments();
postService.deleteAllPosts();
customerService.deleteAllCustomers();
}
@Test
void testPost() {
commentService.deleteAllComment();
commentService.deleteAllComments();
postService.deleteAllPosts();
customerService.deleteAllCustomers();
@ -82,14 +82,14 @@ public class SocialNetworkTest {
Assertions.assertNotEquals(p2.getTitle(), p4.getTitle());
Assertions.assertNotEquals(p2.getContent(), p4.getContent());
commentService.deleteAllComment();
commentService.deleteAllComments();
postService.deleteAllPosts();
customerService.deleteAllCustomers();
}
@Test
void testComment() {
commentService.deleteAllComment();
commentService.deleteAllComments();
postService.deleteAllPosts();
customerService.deleteAllCustomers();
@ -116,7 +116,7 @@ public class SocialNetworkTest {
Assertions.assertNotEquals(com3.getContent(), com4.getContent());
Assertions.assertEquals(com3.getCustomer().getId(), com4.getCustomer().getId());
commentService.deleteAllComment();
commentService.deleteAllComments();
postService.deleteAllPosts();
customerService.deleteAllCustomers();
}