CRUD tested

This commit is contained in:
Catalin Patrut
2021-08-08 13:39:11 +02:00
parent 4a3a9923ef
commit 42e1b15322
12 changed files with 136 additions and 48 deletions

36
pom.xml
View File

@@ -16,6 +16,7 @@
<properties>
<java.version>16</java.version>
<swagger.version>3.0.0</swagger.version>
<mapstruct.version>1.4.2.Final</mapstruct.version>
</properties>
<dependencies>
<dependency>
@@ -77,7 +78,11 @@
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
@@ -100,6 +105,35 @@
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</dependency>
</annotationProcessorPaths>
<compilerArgs>
<compilerArg>
-Amapstruct.defaultComponentModel=spring
</compilerArg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>

View File

@@ -2,26 +2,10 @@ package dev.enblng.api;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
@SpringBootApplication
public class ApiApplication {
public static void main(final String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
.paths(PathSelectors.any())
.build();
}
}

View File

@@ -2,6 +2,7 @@ package dev.enblng.api.api;
import dev.enblng.api.dto.CommentTO;
import dev.enblng.api.services.CommentService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
@@ -16,6 +17,7 @@ import java.util.UUID;
@RestController
@RequestMapping(CommentController.PATH)
@Api(tags = "Comments")
@Slf4j
public class CommentController {
static final String PATH = "comments";

View File

@@ -2,6 +2,7 @@ package dev.enblng.api.api;
import dev.enblng.api.dto.PostTO;
import dev.enblng.api.services.PostService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.HttpStatus;
@@ -15,6 +16,7 @@ import java.util.UUID;
@RestController
@RequestMapping(PostController.PATH)
@Api(tags = "Posts")
@Slf4j
public class PostController {

View File

@@ -3,10 +3,22 @@ package dev.enblng.api.config;
import org.modelmapper.ModelMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
//TODO: delete
@Configuration
public class BeanConfig {
private static final String SNAPSHOT = "1.0";
private static final String HTTP_WWW_APACHE_ORG_LICENSES_LICENSE_2_0_HTML = "Usage of this code is forbidden without consent";
private static final String APACHE_2_0 = "Apache 2.0";
@Bean
public ModelMapper modelMapper() {
final ModelMapper modelMapper = new ModelMapper();
@@ -17,5 +29,26 @@ public class BeanConfig {
return modelMapper;
}
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.useDefaultResponseMessages(false)
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
.paths(PathSelectors.any())
.build()
.apiInfo(apiEndPointsInfo());
}
private ApiInfo apiEndPointsInfo() {
return new ApiInfoBuilder().title("Blog API")
.description("Example of a blog API")
.contact(new Contact("Catalin Patrut", "NO URL", "api@cpatrut.ro"))
.license(APACHE_2_0)
.licenseUrl(HTTP_WWW_APACHE_ORG_LICENSES_LICENSE_2_0_HTML)
.version(SNAPSHOT)
.build();
}
}

View File

@@ -26,11 +26,11 @@ public class CommentTO {
@Size(min = 5, max = 255)
String title;
@ApiModelProperty(position = 2, value = ONLY_FOR_GET_MESSAGE)
@ApiModelProperty(position = 2, value = ONLY_FOR_GET_MESSAGE, example = "George")
@NotNull
String author;
@ApiModelProperty(position = 3, required = true)
@ApiModelProperty(position = 3, required = true, example = "Hello hello")
@Size(min = 10)
@NotNull
String content;
@@ -38,8 +38,6 @@ public class CommentTO {
@ApiModelProperty(position = 5, value = ONLY_FOR_GET_MESSAGE)
String updateTime;
@ApiModelProperty(position = 4, value = ONLY_FOR_GET_MESSAGE)
String creationTime;
@ApiModelProperty(position = 6, value = FOREIGN_KEY_MESSAGE)
UUID postId;
@@ -50,10 +48,9 @@ public class CommentTO {
final String author,
final String content,
final String updateTime,
final String creationTime,
final UUID postId
) {
return new CommentTO(id, title, author, content, updateTime, creationTime, postId);
return new CommentTO(id, title, author, content, updateTime, postId);
}
}

View File

@@ -22,7 +22,7 @@ public class PostTO {
@ApiModelProperty(value = UUID_MESSAGE)
UUID id;
@ApiModelProperty(position = 1, required = true)
@ApiModelProperty(position = 1, required = true, example = "Hello title")
@Size(min = 5, max = 255)
@NotNull
String title;
@@ -30,7 +30,7 @@ public class PostTO {
@ApiModelProperty(value = ONLY_FOR_GET_MESSAGE, position = 2)
String author;
@ApiModelProperty(position = 3, required = true)
@ApiModelProperty(position = 3, required = true, example = "Hello hello")
@Size(min = 10)
@NotNull
String content;
@@ -39,18 +39,13 @@ public class PostTO {
@Null
String updateTime;
@ApiModelProperty(value = ONLY_FOR_GET_MESSAGE, position = 4)
@Null
String creationTime;
@Builder
private static PostTO newPostTo(final UUID id,
final String title,
final String author,
final String content,
final String updateTime,
final String creationTime
final String updateTime
) {
return new PostTO(id, title, author, content, updateTime, creationTime);
return new PostTO(id, title, author, content, updateTime);
}
}

View File

@@ -0,0 +1,14 @@
package dev.enblng.api.mappers;
import dev.enblng.api.dto.CommentTO;
import dev.enblng.api.entities.CommentEntity;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper
public interface CommentMapper {
@Mapping(target = "creationTime", ignore = true)
CommentEntity toEntity(final CommentTO comment);
CommentTO toTransferObject(final CommentEntity comment);
}

View File

@@ -0,0 +1,14 @@
package dev.enblng.api.mappers;
import dev.enblng.api.dto.PostTO;
import dev.enblng.api.entities.PostEntity;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper
public interface PostMapper {
@Mapping(target = "creationTime", ignore = true)
PostEntity toEntity(final PostTO post);
PostTO toTransferObject(final PostEntity post);
}

View File

@@ -25,5 +25,5 @@ public interface CommentRepository extends BlogRepository<CommentEntity, UUID> {
final UUID id);
int deleteById(UUID id);
void deleteById(final UUID id);
}

View File

@@ -2,6 +2,7 @@ package dev.enblng.api.services.impl;
import dev.enblng.api.dto.CommentTO;
import dev.enblng.api.entities.CommentEntity;
import dev.enblng.api.mappers.CommentMapper;
import dev.enblng.api.repositories.CommentRepository;
import dev.enblng.api.services.CommentService;
import org.modelmapper.ModelMapper;
@@ -17,27 +18,31 @@ import java.util.stream.Collectors;
@Service
public class CommentServiceImpl implements CommentService {
private final ModelMapper modelMapper;
private final CommentRepository commentRepository;
private final CommentMapper commentMapper;
public CommentServiceImpl(final ModelMapper modelMapper, final CommentRepository commentRepository) {
this.modelMapper = modelMapper;
public CommentServiceImpl(
final ModelMapper modelMapper,
final CommentRepository commentRepository,
final CommentMapper commentMapper
) {
this.commentMapper = commentMapper;
this.commentRepository = commentRepository;
}
@Override
@Transactional
public CommentTO save(final CommentTO comment) {
final CommentEntity entity = modelMapper.map(comment, CommentEntity.class);
final CommentEntity entity = commentMapper.toEntity(comment);
entity.setId(UUID.randomUUID());
return modelMapper.map(commentRepository.save(entity), CommentTO.CommentTOBuilder.class).build();
return commentMapper.toTransferObject(commentRepository.save(entity));
}
@Override
@Transactional
public List<CommentTO> getByPostId(final UUID id, final Pageable pageable) {
return commentRepository.findAllByPostIdOrderByCreationTime(id, pageable)
.map(commentEntity -> modelMapper.map(commentEntity,
CommentTO.CommentTOBuilder.class).build())
.map(commentMapper::toTransferObject)
.collect(Collectors.toList());
}

View File

@@ -2,49 +2,57 @@ package dev.enblng.api.services.impl;
import dev.enblng.api.dto.PostTO;
import dev.enblng.api.entities.PostEntity;
import dev.enblng.api.mappers.PostMapper;
import dev.enblng.api.repositories.PostRepository;
import dev.enblng.api.services.PostService;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import javax.persistence.EntityNotFoundException;
import javax.transaction.Transactional;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
@Service
@Slf4j
public class PostServiceImpl implements PostService {
private final PostRepository postRepository;
private final ModelMapper modelMapper;
private final PostMapper postMapper;
@Autowired
public PostServiceImpl(final ModelMapper modelMapper, final PostRepository postRepository) {
this.modelMapper = modelMapper;
public PostServiceImpl(final ModelMapper modelMapper,
final PostRepository postRepository,
final PostMapper postMapper) {
this.postRepository = postRepository;
this.postMapper = postMapper;
}
@Override
@Transactional
public PostTO save(final PostTO post) {
final PostEntity entity = modelMapper.map(post, PostEntity.class);
final PostEntity entity = postMapper.toEntity(post);
log.debug(post.toString());
entity.setId(UUID.randomUUID());
return modelMapper.map(postRepository.save(entity), PostTO.PostTOBuilder.class)
.build();
final PostEntity savedEntity = postRepository.save(entity);
return postMapper.toTransferObject(savedEntity);
}
@Override
public PostTO getById(final UUID id) {
final PostEntity entity = postRepository.getById(id)
.orElseThrow(EntityNotFoundException::new);
return modelMapper.map(entity, PostTO.PostTOBuilder.class).build();
return postMapper.toTransferObject(entity);
}
@Override
public List<PostTO> findAll(final Pageable pageable) {
return postRepository.findAll(pageable).get()
.map(postEntity -> modelMapper.map(postEntity, PostTO.PostTOBuilder.class).build())
.map(postMapper::toTransferObject)
.collect(Collectors.toList());
}