From 79a288d92145071402a39e096d62e7a8924e65eb Mon Sep 17 00:00:00 2001 From: springframeworkguru Date: Fri, 11 Jan 2019 06:24:27 +0530 Subject: [PATCH] Added vendor and moved the URL setting from the service implementation into the mapper. This allows a single place for the URL to be set, thus simplifying the service implementation. In my point of view, the setting of the URL is more a mappers function than the service. Hopefully you agree. --- pom.xml | 29 ++++--- .../api/v1/mapper/CustomerMapper.java | 13 ++++ .../api/v1/mapper/VendorMapper.java | 30 +++++++ .../api/v1/model/VendorDTO.java | 18 +++++ .../api/v1/model/VendorListDTO.java | 15 ++++ .../springfamework/bootstrap/Bootstrap.java | 28 ++++++- .../controllers/v1/VendorController.java | 78 +++++++++++++++++++ .../guru/springfamework/domain/Vendor.java | 19 +++++ .../repositories/VendorRepository.java | 9 +++ .../services/CustomerServiceImpl.java | 31 +------- .../services/VendorService.java | 21 +++++ .../services/VendorServiceImpl.java | 77 ++++++++++++++++++ .../api/v1/mapper/VendorMapperTest.java | 35 +++++++++ .../services/CustomerServiceImplIT.java | 7 +- 14 files changed, 372 insertions(+), 38 deletions(-) create mode 100644 src/main/java/guru/springfamework/api/v1/mapper/VendorMapper.java create mode 100644 src/main/java/guru/springfamework/api/v1/model/VendorDTO.java create mode 100644 src/main/java/guru/springfamework/api/v1/model/VendorListDTO.java create mode 100644 src/main/java/guru/springfamework/controllers/v1/VendorController.java create mode 100644 src/main/java/guru/springfamework/domain/Vendor.java create mode 100644 src/main/java/guru/springfamework/repositories/VendorRepository.java create mode 100644 src/main/java/guru/springfamework/services/VendorService.java create mode 100644 src/main/java/guru/springfamework/services/VendorServiceImpl.java create mode 100644 src/test/java/guru/springfamework/api/v1/mapper/VendorMapperTest.java diff --git a/pom.xml b/pom.xml index f72728ea4..3bd340585 100644 --- a/pom.xml +++ b/pom.xml @@ -21,8 +21,9 @@ UTF-8 UTF-8 - 1.8 - 1.2.0.CR2 + 11 + 1.4.2.Final + 1.18.24 @@ -47,13 +48,14 @@ org.projectlombok lombok + ${org.projectlombok.version} provided - org.mapstruct - mapstruct-jdk8 - ${org.mapstruct.version} - + org.mapstruct + mapstruct + ${org.mapstruct.version} + org.springframework.boot spring-boot-starter-test @@ -79,18 +81,27 @@ + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + false + + + org.apache.maven.plugins maven-compiler-plugin 3.7.0 - 1.8 - 1.8 + 11 + 11 org.projectlombok lombok - ${lombok.version} + ${org.projectlombok.version} org.mapstruct diff --git a/src/main/java/guru/springfamework/api/v1/mapper/CustomerMapper.java b/src/main/java/guru/springfamework/api/v1/mapper/CustomerMapper.java index 682dc333e..a2a6a74b7 100644 --- a/src/main/java/guru/springfamework/api/v1/mapper/CustomerMapper.java +++ b/src/main/java/guru/springfamework/api/v1/mapper/CustomerMapper.java @@ -1,8 +1,13 @@ package guru.springfamework.api.v1.mapper; import guru.springfamework.api.v1.model.CustomerDTO; +import guru.springfamework.controllers.v1.CustomerController; import guru.springfamework.domain.Customer; + +import org.mapstruct.AfterMapping; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; import org.mapstruct.factory.Mappers; /** @@ -13,7 +18,15 @@ public interface CustomerMapper { CustomerMapper INSTANCE = Mappers.getMapper(CustomerMapper.class); + @Mapping(source = "id", target = "customerUrl") CustomerDTO customerToCustomerDTO(Customer customer); + + @AfterMapping + default void addBaseURL(@MappingTarget CustomerDTO customerDTO) + { + customerDTO.setCustomerUrl(CustomerController.BASE_URL + "/" + customerDTO.getCustomerUrl()); + } + @Mapping(target = "id", ignore = true) Customer customerDtoToCustomer(CustomerDTO customerDTO); } diff --git a/src/main/java/guru/springfamework/api/v1/mapper/VendorMapper.java b/src/main/java/guru/springfamework/api/v1/mapper/VendorMapper.java new file mode 100644 index 000000000..ebf6c2914 --- /dev/null +++ b/src/main/java/guru/springfamework/api/v1/mapper/VendorMapper.java @@ -0,0 +1,30 @@ +package guru.springfamework.api.v1.mapper; + +import org.mapstruct.AfterMapping; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.factory.Mappers; + +import guru.springfamework.api.v1.model.VendorDTO; +import guru.springfamework.controllers.v1.VendorController; +import guru.springfamework.domain.Vendor; + +@Mapper +public interface VendorMapper +{ + VendorMapper INSTANCE = Mappers.getMapper(VendorMapper.class); + + @Mapping(source = "id", target = "vendorUrl") + VendorDTO vendorToVendorDTO(Vendor vendor); + + @AfterMapping + default void addBaseURL(@MappingTarget VendorDTO vendorDTO) + { + vendorDTO.setVendorUrl(VendorController.BASE_URL + "/" + vendorDTO.getVendorUrl()); + } + + @Mapping(target = "id", ignore = true) + Vendor vendorDtoToVendor(VendorDTO vendorDTO); + +} diff --git a/src/main/java/guru/springfamework/api/v1/model/VendorDTO.java b/src/main/java/guru/springfamework/api/v1/model/VendorDTO.java new file mode 100644 index 000000000..3caf1f592 --- /dev/null +++ b/src/main/java/guru/springfamework/api/v1/model/VendorDTO.java @@ -0,0 +1,18 @@ +package guru.springfamework.api.v1.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class VendorDTO +{ + private String name; + + @JsonProperty("vendor_url") + private String vendorUrl; +} diff --git a/src/main/java/guru/springfamework/api/v1/model/VendorListDTO.java b/src/main/java/guru/springfamework/api/v1/model/VendorListDTO.java new file mode 100644 index 000000000..95eb1ca53 --- /dev/null +++ b/src/main/java/guru/springfamework/api/v1/model/VendorListDTO.java @@ -0,0 +1,15 @@ +package guru.springfamework.api.v1.model; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class VendorListDTO +{ + private List vendors; +} diff --git a/src/main/java/guru/springfamework/bootstrap/Bootstrap.java b/src/main/java/guru/springfamework/bootstrap/Bootstrap.java index cd24a56f6..6db684c91 100644 --- a/src/main/java/guru/springfamework/bootstrap/Bootstrap.java +++ b/src/main/java/guru/springfamework/bootstrap/Bootstrap.java @@ -2,8 +2,11 @@ import guru.springfamework.domain.Category; import guru.springfamework.domain.Customer; +import guru.springfamework.domain.Vendor; import guru.springfamework.repositories.CategoryRepository; import guru.springfamework.repositories.CustomerRepository; +import guru.springfamework.repositories.VendorRepository; + import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; @@ -15,10 +18,12 @@ public class Bootstrap implements CommandLineRunner{ private final CategoryRepository categoryRespository; private final CustomerRepository customerRepository; + private final VendorRepository vendorRepository; - public Bootstrap(CategoryRepository categoryRespository, CustomerRepository customerRepository) { + public Bootstrap(CategoryRepository categoryRespository, CustomerRepository customerRepository, VendorRepository vendorRepository) { this.categoryRespository = categoryRespository; this.customerRepository = customerRepository; + this.vendorRepository = vendorRepository; } @Override @@ -26,6 +31,7 @@ public void run(String... args) throws Exception { loadCategories(); loadCustomers(); + loadVendors(); } private void loadCategories() { @@ -70,4 +76,24 @@ private void loadCustomers() { System.out.println("Customers Loaded: " + customerRepository.count()); } + + private void loadVendors() + { + Vendor vendor = new Vendor(); + vendor.setId(1L); + vendor.setName("vendor 1"); + vendorRepository.save(vendor); + + vendor = new Vendor(); + vendor.setId(2L); + vendor.setName("vendor 2"); + vendorRepository.save(vendor); + + vendor = new Vendor(); + vendor.setId(3L); + vendor.setName("vendor 3"); + vendorRepository.save(vendor); + + System.out.println("Vendors Loaded: " + vendorRepository.count()); + } } diff --git a/src/main/java/guru/springfamework/controllers/v1/VendorController.java b/src/main/java/guru/springfamework/controllers/v1/VendorController.java new file mode 100644 index 000000000..bba1e8d11 --- /dev/null +++ b/src/main/java/guru/springfamework/controllers/v1/VendorController.java @@ -0,0 +1,78 @@ +package guru.springfamework.controllers.v1; + +import java.util.List; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import guru.springfamework.api.v1.model.VendorDTO; +import guru.springfamework.services.VendorService; + +@RestController() +@RequestMapping(VendorController.BASE_URL) +public class VendorController +{ + public static final String BASE_URL = "/api/v1/vendors"; + + public VendorController(VendorService vendorService) + { + this.vendorService = vendorService; + } + + private final VendorService vendorService; + + @GetMapping + @ResponseStatus(HttpStatus.OK) + List getVendors() + { + return vendorService.getAllVendors(); + } + + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + VendorDTO createVendor(@RequestBody VendorDTO vendorDTO) + { + VendorDTO createdVendor = vendorService.createNewVendor(vendorDTO); + + return createdVendor; + } + + @DeleteMapping("/{id}") + @ResponseStatus(HttpStatus.OK) + void deleteVendor(@PathVariable Long id) + { + vendorService.deleteVendorById(id); + } + + @GetMapping("/{id}") + @ResponseStatus(HttpStatus.OK) + VendorDTO getVendor(@PathVariable Long id) + { + return vendorService.getVendorById(id); + } + + + @PutMapping("/{id}") + @ResponseStatus(HttpStatus.OK) + VendorDTO updateVendor(@PathVariable Long id, @RequestBody VendorDTO vendorDTO) + { + return vendorService.saveVendorByDTO(id, vendorDTO); + } + + @PatchMapping("/{id}") + @ResponseStatus(HttpStatus.OK) + VendorDTO patchVendor(@PathVariable Long id, @RequestBody VendorDTO vendorDTO) + { + return vendorService.patchVendor(id, vendorDTO); + } + +} diff --git a/src/main/java/guru/springfamework/domain/Vendor.java b/src/main/java/guru/springfamework/domain/Vendor.java new file mode 100644 index 000000000..77c8e9340 --- /dev/null +++ b/src/main/java/guru/springfamework/domain/Vendor.java @@ -0,0 +1,19 @@ +package guru.springfamework.domain; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +import lombok.Data; + +@Entity +@Data +public class Vendor +{ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; +} diff --git a/src/main/java/guru/springfamework/repositories/VendorRepository.java b/src/main/java/guru/springfamework/repositories/VendorRepository.java new file mode 100644 index 000000000..aab7161d2 --- /dev/null +++ b/src/main/java/guru/springfamework/repositories/VendorRepository.java @@ -0,0 +1,9 @@ +package guru.springfamework.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; + +import guru.springfamework.domain.Vendor; + +public interface VendorRepository extends JpaRepository { + +} diff --git a/src/main/java/guru/springfamework/services/CustomerServiceImpl.java b/src/main/java/guru/springfamework/services/CustomerServiceImpl.java index 18d3a7b95..4455f1434 100644 --- a/src/main/java/guru/springfamework/services/CustomerServiceImpl.java +++ b/src/main/java/guru/springfamework/services/CustomerServiceImpl.java @@ -2,7 +2,6 @@ import guru.springfamework.api.v1.mapper.CustomerMapper; import guru.springfamework.api.v1.model.CustomerDTO; -import guru.springfamework.controllers.v1.CustomerController; import guru.springfamework.domain.Customer; import guru.springfamework.repositories.CustomerRepository; import org.springframework.stereotype.Service; @@ -29,11 +28,7 @@ public List getAllCustomers() { return customerRepository .findAll() .stream() - .map(customer -> { - CustomerDTO customerDTO = customerMapper.customerToCustomerDTO(customer); - customerDTO.setCustomerUrl(getCustomerUrl(customer.getId())); - return customerDTO; - }) + .map(customerMapper::customerToCustomerDTO) .collect(Collectors.toList()); } @@ -42,11 +37,6 @@ public CustomerDTO getCustomerById(Long id) { return customerRepository.findById(id) .map(customerMapper::customerToCustomerDTO) - .map(customerDTO -> { - //set API URL - customerDTO.setCustomerUrl(getCustomerUrl(id)); - return customerDTO; - }) .orElseThrow(ResourceNotFoundException::new); } @@ -57,13 +47,8 @@ public CustomerDTO createNewCustomer(CustomerDTO customerDTO) { } private CustomerDTO saveAndReturnDTO(Customer customer) { - Customer savedCustomer = customerRepository.save(customer); - - CustomerDTO returnDto = customerMapper.customerToCustomerDTO(savedCustomer); - - returnDto.setCustomerUrl(getCustomerUrl(savedCustomer.getId())); - - return returnDto; + + return customerMapper.customerToCustomerDTO(customerRepository.save(customer)); } @Override @@ -86,19 +71,11 @@ public CustomerDTO patchCustomer(Long id, CustomerDTO customerDTO) { customer.setLastname(customerDTO.getLastname()); } - CustomerDTO returnDto = customerMapper.customerToCustomerDTO(customerRepository.save(customer)); - - returnDto.setCustomerUrl(getCustomerUrl(id)); - - return returnDto; + return customerMapper.customerToCustomerDTO(customerRepository.save(customer)); }).orElseThrow(ResourceNotFoundException::new); } - private String getCustomerUrl(Long id) { - return CustomerController.BASE_URL + "/" + id; - } - @Override public void deleteCustomerById(Long id) { customerRepository.deleteById(id); diff --git a/src/main/java/guru/springfamework/services/VendorService.java b/src/main/java/guru/springfamework/services/VendorService.java new file mode 100644 index 000000000..62b6ed9f6 --- /dev/null +++ b/src/main/java/guru/springfamework/services/VendorService.java @@ -0,0 +1,21 @@ +package guru.springfamework.services; + +import java.util.List; + +import guru.springfamework.api.v1.model.VendorDTO; + + +public interface VendorService +{ + List getAllVendors(); + + VendorDTO getVendorById(Long id); + + VendorDTO createNewVendor(VendorDTO vendorDTO); + + VendorDTO saveVendorByDTO(Long id, VendorDTO vendorDTO); + + VendorDTO patchVendor(Long id, VendorDTO vendorDTO); + + void deleteVendorById(Long id); +} diff --git a/src/main/java/guru/springfamework/services/VendorServiceImpl.java b/src/main/java/guru/springfamework/services/VendorServiceImpl.java new file mode 100644 index 000000000..5f33c3e8c --- /dev/null +++ b/src/main/java/guru/springfamework/services/VendorServiceImpl.java @@ -0,0 +1,77 @@ +package guru.springfamework.services; + +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; + +import guru.springfamework.api.v1.mapper.VendorMapper; +import guru.springfamework.api.v1.model.VendorDTO; +import guru.springfamework.domain.Vendor; +import guru.springfamework.repositories.VendorRepository; + +@Service +public class VendorServiceImpl implements VendorService +{ + private final VendorRepository vendorRepository; + private final VendorMapper vendorMapper; + + + public VendorServiceImpl(VendorRepository vendorRepository, VendorMapper vendorMapper) + { + this.vendorRepository = vendorRepository; + this.vendorMapper = vendorMapper; + + } + + @Override + public List getAllVendors() + { + return vendorRepository.findAll() + .stream() + .map(vendorMapper::vendorToVendorDTO) + .collect(Collectors.toList()); + } + + @Override + public VendorDTO getVendorById(Long id) + { + return vendorMapper.vendorToVendorDTO(vendorRepository.findById(id).orElseThrow(ResourceNotFoundException::new)); + } + + @Override + public VendorDTO createNewVendor(VendorDTO vendorDTO) + { + return vendorMapper.vendorToVendorDTO(vendorRepository.save(vendorMapper.vendorDtoToVendor(vendorDTO))); + } + + private VendorDTO updateEntity(Long id, VendorDTO vendorDTO, boolean isUpdate) + { + Vendor vendor = vendorRepository.findById(id).orElseThrow(ResourceNotFoundException::new); + + if(isUpdate || vendorDTO.getName() != null) + { + vendor.setName(vendorDTO.getName()); + vendorDTO = vendorMapper.vendorToVendorDTO(vendorRepository.save(vendor)); + } + + return vendorDTO; + } + + @Override + public VendorDTO saveVendorByDTO(Long id, VendorDTO vendorDTO) { + return updateEntity(id, vendorDTO, true); + } + + @Override + public VendorDTO patchVendor(Long id, VendorDTO vendorDTO) { + + return updateEntity(id, vendorDTO, false); + } + + @Override + public void deleteVendorById(Long id) + { + vendorRepository.deleteById(id); + } +} diff --git a/src/test/java/guru/springfamework/api/v1/mapper/VendorMapperTest.java b/src/test/java/guru/springfamework/api/v1/mapper/VendorMapperTest.java new file mode 100644 index 000000000..8a4c60e07 --- /dev/null +++ b/src/test/java/guru/springfamework/api/v1/mapper/VendorMapperTest.java @@ -0,0 +1,35 @@ +package guru.springfamework.api.v1.mapper; + + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import guru.springfamework.api.v1.model.VendorDTO; +import guru.springfamework.controllers.v1.VendorController; +import guru.springfamework.domain.Vendor; + + +public class VendorMapperTest +{ + public static final Long ID = 1L; + public static final String NAME = "Test Vendor"; + VendorMapper vendorMapper = VendorMapper.INSTANCE; + + @Test + public void vendorToVendorDTO() throws Exception { + //given + Vendor vendor = new Vendor(); + vendor.setId(ID); + vendor.setName(NAME); + + //when + VendorDTO vendorDTO = vendorMapper.vendorToVendorDTO(vendor); + + //then + assertEquals(NAME, vendorDTO.getName()); + assertEquals(VendorController.BASE_URL + "/" + ID, vendorDTO.getVendorUrl()); + + + } +} diff --git a/src/test/java/guru/springfamework/services/CustomerServiceImplIT.java b/src/test/java/guru/springfamework/services/CustomerServiceImplIT.java index 4ce63be18..82938b0e7 100644 --- a/src/test/java/guru/springfamework/services/CustomerServiceImplIT.java +++ b/src/test/java/guru/springfamework/services/CustomerServiceImplIT.java @@ -6,6 +6,8 @@ import guru.springfamework.domain.Customer; import guru.springfamework.repositories.CategoryRepository; import guru.springfamework.repositories.CustomerRepository; +import guru.springfamework.repositories.VendorRepository; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -33,6 +35,9 @@ public class CustomerServiceImplIT { @Autowired CategoryRepository categoryRepository; + + @Autowired + VendorRepository vendorRepository; CustomerService customerService; @@ -42,7 +47,7 @@ public void setUp() throws Exception { System.out.println(customerRepository.findAll().size()); //setup data for testing - Bootstrap bootstrap = new Bootstrap(categoryRepository, customerRepository); + Bootstrap bootstrap = new Bootstrap(categoryRepository, customerRepository, vendorRepository); bootstrap.run(); //load data customerService = new CustomerServiceImpl(CustomerMapper.INSTANCE, customerRepository);