mirror of
https://github.com/robindhole/sfg-restdocs-example.git
synced 2025-09-13 18:42:23 +00:00
intial project add
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
package guru.springframework.sfgrestdocsexample;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SfgRestdocsExampleApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SfgRestdocsExampleApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
package guru.springframework.sfgrestdocsexample.bootstrap;
|
||||
|
||||
import guru.springframework.sfgrestdocsexample.domain.Beer;
|
||||
import guru.springframework.sfgrestdocsexample.repositories.BeerRepository;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* Created by jt on 2019-05-17.
|
||||
*/
|
||||
@Component
|
||||
public class BeerLoader implements CommandLineRunner {
|
||||
|
||||
private final BeerRepository beerRepository;
|
||||
|
||||
public BeerLoader(BeerRepository beerRepository) {
|
||||
this.beerRepository = beerRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
loadBeerObjects();
|
||||
}
|
||||
|
||||
private void loadBeerObjects() {
|
||||
if(beerRepository.count() == 0){
|
||||
|
||||
beerRepository.save(Beer.builder()
|
||||
.beerName("Mango Bobs")
|
||||
.beerStyle("IPA")
|
||||
.quantityToBrew(200)
|
||||
.minOnHand(12)
|
||||
.upc(337010000001L)
|
||||
.price(new BigDecimal("12.95"))
|
||||
.build());
|
||||
|
||||
beerRepository.save(Beer.builder()
|
||||
.beerName("Galaxy Cat")
|
||||
.beerStyle("PALE_ALE")
|
||||
.quantityToBrew(200)
|
||||
.minOnHand(12)
|
||||
.upc(337010000002L)
|
||||
.price(new BigDecimal("11.95"))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
package guru.springframework.sfgrestdocsexample.domain;
|
||||
|
||||
import lombok.*;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.UpdateTimestamp;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created by jt on 2019-05-17.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Entity
|
||||
public class Beer {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(generator = "UUID")
|
||||
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
|
||||
@Column(length = 36, columnDefinition = "varchar", updatable = false, nullable = false)
|
||||
private UUID id;
|
||||
|
||||
@Version
|
||||
private Long version;
|
||||
|
||||
@CreationTimestamp
|
||||
@Column(updatable = false)
|
||||
private Timestamp createdDate;
|
||||
|
||||
@UpdateTimestamp
|
||||
private Timestamp lastModifiedDate;
|
||||
|
||||
private String beerName;
|
||||
private String beerStyle;
|
||||
|
||||
@Column(unique = true)
|
||||
private Long upc;
|
||||
|
||||
private BigDecimal price;
|
||||
|
||||
private Integer minOnHand;
|
||||
private Integer quantityToBrew;
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package guru.springframework.sfgrestdocsexample.repositories;
|
||||
|
||||
import guru.springframework.sfgrestdocsexample.domain.Beer;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created by jt on 2019-05-17.
|
||||
*/
|
||||
public interface BeerRepository extends PagingAndSortingRepository<Beer, UUID> {
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
package guru.springframework.sfgrestdocsexample.web.controller;
|
||||
|
||||
import guru.springframework.sfgrestdocsexample.web.model.BeerDto;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created by jt on 2019-05-12.
|
||||
*/
|
||||
@RequestMapping("/api/v1/beer")
|
||||
@RestController
|
||||
public class BeerController {
|
||||
|
||||
|
||||
@GetMapping("/{beerId}")
|
||||
public ResponseEntity<BeerDto> getBeerById(@PathVariable("beerId") UUID beerId){
|
||||
|
||||
//todo impl
|
||||
return new ResponseEntity<>(BeerDto.builder().build(), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity saveNewBeer(@RequestBody @Validated BeerDto beerDto){
|
||||
|
||||
//todo impl
|
||||
return new ResponseEntity(HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@PutMapping("/{beerId}")
|
||||
public ResponseEntity updateBeerById(@PathVariable("beerId") UUID beerId, @RequestBody @Validated BeerDto beerDto){
|
||||
|
||||
//todo impl
|
||||
return new ResponseEntity(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
package guru.springframework.sfgrestdocsexample.web.controller;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by jt on 2019-05-25.
|
||||
*/
|
||||
@ControllerAdvice
|
||||
public class MvcExceptionHandler {
|
||||
|
||||
@ExceptionHandler(ConstraintViolationException.class)
|
||||
public ResponseEntity<List> validationErrorHandler(ConstraintViolationException ex){
|
||||
List<String> errorsList = new ArrayList<>(ex.getConstraintViolations().size());
|
||||
|
||||
ex.getConstraintViolations().forEach(error -> errorsList.add(error.toString()));
|
||||
|
||||
return new ResponseEntity<>(errorsList, HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
package guru.springframework.sfgrestdocsexample.web.mappers;
|
||||
|
||||
import guru.springframework.sfgrestdocsexample.domain.Beer;
|
||||
import guru.springframework.sfgrestdocsexample.web.model.BeerDto;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
/**
|
||||
* Created by jt on 2019-05-25.
|
||||
*/
|
||||
@Mapper(uses = {DateMapper.class})
|
||||
public interface BeerMapper {
|
||||
|
||||
BeerDto BeerToBeerDto(Beer beer);
|
||||
|
||||
Beer BeerDtoToBeer(BeerDto dto);
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
package guru.springframework.sfgrestdocsexample.web.mappers;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
/**
|
||||
* Created by jt on 2019-05-25.
|
||||
*/
|
||||
@Component
|
||||
public class DateMapper {
|
||||
public OffsetDateTime asOffsetDateTime(Timestamp ts){
|
||||
if (ts != null){
|
||||
return OffsetDateTime.of(ts.toLocalDateTime().getYear(), ts.toLocalDateTime().getMonthValue(),
|
||||
ts.toLocalDateTime().getDayOfMonth(), ts.toLocalDateTime().getHour(), ts.toLocalDateTime().getMinute(),
|
||||
ts.toLocalDateTime().getSecond(), ts.toLocalDateTime().getNano(), ZoneOffset.UTC);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Timestamp asTimestamp(OffsetDateTime offsetDateTime){
|
||||
if(offsetDateTime != null) {
|
||||
return Timestamp.valueOf(offsetDateTime.atZoneSameInstant(ZoneOffset.UTC).toLocalDateTime());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
package guru.springframework.sfgrestdocsexample.web.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Null;
|
||||
import javax.validation.constraints.Positive;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created by jt on 2019-05-12.
|
||||
*/
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class BeerDto {
|
||||
|
||||
@Null
|
||||
private UUID id;
|
||||
|
||||
@Null
|
||||
private Integer version;
|
||||
|
||||
@Null
|
||||
private OffsetDateTime createdDate;
|
||||
|
||||
@Null
|
||||
private OffsetDateTime lastModifiedDate;
|
||||
|
||||
@NotBlank
|
||||
private String beerName;
|
||||
|
||||
@NotNull
|
||||
private BeerStyleEnum beerStyle;
|
||||
|
||||
@Positive
|
||||
@NotNull
|
||||
private Long upc;
|
||||
|
||||
@Positive
|
||||
@NotNull
|
||||
private BigDecimal price;
|
||||
|
||||
private Integer quantityOnHand;
|
||||
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package guru.springframework.sfgrestdocsexample.web.model;
|
||||
|
||||
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by jt on 2019-05-12.
|
||||
*/
|
||||
public class BeerPagedList extends PageImpl<BeerDto> {
|
||||
|
||||
public BeerPagedList(List<BeerDto> content, Pageable pageable, long total) {
|
||||
super(content, pageable, total);
|
||||
}
|
||||
|
||||
public BeerPagedList(List<BeerDto> content) {
|
||||
super(content);
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
package guru.springframework.sfgrestdocsexample.web.model;
|
||||
|
||||
/**
|
||||
* Created by jt on 2019-05-12.
|
||||
*/
|
||||
public enum BeerStyleEnum {
|
||||
LAGER, PILSNER, STOUT, GOSE, PORTER, ALE, WHEAT, IPA, PALE_ALE, SAISON
|
||||
}
|
1
src/main/resources/application.properties
Normal file
1
src/main/resources/application.properties
Normal file
@@ -0,0 +1 @@
|
||||
|
@@ -0,0 +1,14 @@
|
||||
package guru.springframework.sfgrestdocsexample;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
public class SfgRestdocsExampleApplicationTests {
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
package guru.springframework.sfgrestdocsexample.web.controller;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import guru.springframework.sfgrestdocsexample.web.model.BeerDto;
|
||||
import guru.springframework.sfgrestdocsexample.web.model.BeerStyleEnum;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@WebMvcTest(BeerController.class)
|
||||
class BeerControllerTest {
|
||||
|
||||
@Autowired
|
||||
MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
ObjectMapper objectMapper;
|
||||
|
||||
@Test
|
||||
void getBeerById() throws Exception {
|
||||
mockMvc.perform(get("/api/v1/beer/" + UUID.randomUUID().toString()).accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveNewBeer() throws Exception {
|
||||
BeerDto beerDto = getValidBeerDto();
|
||||
String beerDtoJson = objectMapper.writeValueAsString(beerDto);
|
||||
|
||||
mockMvc.perform(post("/api/v1/beer/")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(beerDtoJson))
|
||||
.andExpect(status().isCreated());
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateBeerById() throws Exception {
|
||||
BeerDto beerDto = getValidBeerDto();
|
||||
String beerDtoJson = objectMapper.writeValueAsString(beerDto);
|
||||
|
||||
mockMvc.perform(put("/api/v1/beer/" + UUID.randomUUID().toString())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(beerDtoJson))
|
||||
.andExpect(status().isNoContent());
|
||||
}
|
||||
|
||||
BeerDto getValidBeerDto(){
|
||||
return BeerDto.builder()
|
||||
.beerName("Nice Ale")
|
||||
.beerStyle(BeerStyleEnum.ALE)
|
||||
.price(new BigDecimal("9.99"))
|
||||
.upc(123123123123L)
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user