From ffc5647cf946c538b2d6ad10a70a24c7691678f6 Mon Sep 17 00:00:00 2001 From: Alexey Zinchenko Date: Sun, 12 May 2019 03:44:05 +0300 Subject: [PATCH] Added logging. Small refactoring. --- pom.xml | 32 ++++++++++------- .../controller/ClientController.java | 14 ++++++-- .../carrepair/controller/HomeController.java | 6 +++- .../controller/MechanicController.java | 36 ++++++++++++------- .../carrepair/controller/OrderController.java | 13 +++++-- .../carrepair/demo/DemoDataPopulator.java | 24 +++++++------ .../formatter/CustomDateTimeFormatter.java | 12 +++++-- .../formatter/OrderStatusFormatter.java | 12 +++++-- .../repository/spec/OrderSpecifications.java | 5 +++ .../carrepair/service/ClientService.java | 25 ++++++++++--- .../carrepair/service/MechanicService.java | 26 +++++++++++--- .../carrepair/service/OrderService.java | 25 ++++++++++--- .../carrepair/validation/OrderValidator.java | 12 +++++-- src/main/resources/application.properties | 2 +- src/main/resources/log4j2.properties | 23 ++++++++++++ .../templates/{home.html => index.html} | 0 16 files changed, 205 insertions(+), 62 deletions(-) create mode 100644 src/main/resources/log4j2.properties rename src/main/resources/templates/{home.html => index.html} (100%) diff --git a/pom.xml b/pom.xml index 8011301..eced845 100644 --- a/pom.xml +++ b/pom.xml @@ -26,11 +26,12 @@ org.springframework.boot spring-boot-starter-thymeleaf - - - nz.net.ultraq.thymeleaf - thymeleaf-layout-dialect - 2.3.0 + + + org.springframework.boot + spring-boot-starter-logging + + org.springframework.boot @@ -42,23 +43,30 @@ spring-boot-devtools true + + org.springframework.boot + spring-boot-starter-test + test + + + nz.net.ultraq.thymeleaf + thymeleaf-layout-dialect + 2.3.0 + + + org.springframework.boot + spring-boot-starter-log4j2 + org.liquibase liquibase-core - mysql mysql-connector-java 8.0.16 runtime - - org.springframework.boot - spring-boot-starter-test - test - - com.github.javafaker javafaker diff --git a/src/main/java/com/github/prominence/carrepair/controller/ClientController.java b/src/main/java/com/github/prominence/carrepair/controller/ClientController.java index f66f198..143b484 100644 --- a/src/main/java/com/github/prominence/carrepair/controller/ClientController.java +++ b/src/main/java/com/github/prominence/carrepair/controller/ClientController.java @@ -2,6 +2,8 @@ package com.github.prominence.carrepair.controller; import com.github.prominence.carrepair.model.Client; import com.github.prominence.carrepair.service.ClientService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; @@ -19,6 +21,8 @@ import java.util.Optional; @RequestMapping("/client") public class ClientController { + private static final Logger logger = LogManager.getLogger(ClientController.class); + private ClientService clientService; public ClientController(ClientService clientService) { @@ -28,6 +32,7 @@ public class ClientController { @GetMapping public String index(@PageableDefault Pageable pageable, ModelMap modelMap) { Page clientList = clientService.findAll(pageable); + logger.trace("Request to open list page for Clients. Returning {} page.", () -> pageable.getPageNumber() + 1); modelMap.addAttribute("clientList", clientList.getContent()); modelMap.addAttribute("totalPages", clientList.getTotalPages()); @@ -37,6 +42,7 @@ public class ClientController { @GetMapping(value = "/create") public String create(Model model) { + logger.trace("Request to open create page for Client."); model.addAttribute("client", new Client()); return "client/edit"; @@ -44,19 +50,21 @@ public class ClientController { @GetMapping(value = "/edit/{id}") public String edit(@PathVariable Long id, Model model) { + logger.trace("Request to open edit page for Client[{}].", () -> id); Optional clientOptional = clientService.findById(id); if (clientOptional.isPresent()) { model.addAttribute("client", clientOptional.get()); return "client/edit"; } else { - // TODO: need to show warning return "redirect:/client"; } } @PostMapping(value = "/update/{id}") public String update(@Valid Client client, BindingResult bindingResult, @PathVariable long id) { + logger.trace("Request to save {}.", () -> client); if (bindingResult.hasErrors()) { + logger.trace("{} has validation {} errors and won't be saved.", () -> client, bindingResult::getErrorCount); client.setId(id); // why should we do this? return "client/edit"; } @@ -67,7 +75,9 @@ public class ClientController { @PostMapping(value = "/create") public String save(@Valid Client client, BindingResult bindingResult) { + logger.trace("Request to create {}.", () -> client); if (bindingResult.hasErrors()) { + logger.trace("{} has validation {} errors and won't be created.", () -> client, bindingResult::getErrorCount); return "client/edit"; } @@ -77,8 +87,8 @@ public class ClientController { @DeleteMapping(value = "/delete/{id}") public ResponseEntity delete(@PathVariable Long id) { + logger.trace("Request to delete Client[{}].", () -> id); boolean deleteSuccess = clientService.deleteClientById(id); - if (deleteSuccess) { return ResponseEntity.ok().build(); } else { diff --git a/src/main/java/com/github/prominence/carrepair/controller/HomeController.java b/src/main/java/com/github/prominence/carrepair/controller/HomeController.java index 37dc92b..4d3d271 100644 --- a/src/main/java/com/github/prominence/carrepair/controller/HomeController.java +++ b/src/main/java/com/github/prominence/carrepair/controller/HomeController.java @@ -1,14 +1,18 @@ package com.github.prominence.carrepair.controller; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/") public class HomeController { + private static final Logger logger = LogManager.getLogger(HomeController.class); @RequestMapping public String index() { - return "home"; + logger.trace("Request to open home page."); + return "index"; } } diff --git a/src/main/java/com/github/prominence/carrepair/controller/MechanicController.java b/src/main/java/com/github/prominence/carrepair/controller/MechanicController.java index 525f56f..d18d781 100644 --- a/src/main/java/com/github/prominence/carrepair/controller/MechanicController.java +++ b/src/main/java/com/github/prominence/carrepair/controller/MechanicController.java @@ -3,6 +3,8 @@ package com.github.prominence.carrepair.controller; import com.github.prominence.carrepair.enums.OrderStatus; import com.github.prominence.carrepair.model.Mechanic; import com.github.prominence.carrepair.service.MechanicService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; @@ -20,6 +22,7 @@ import java.util.Optional; @Controller @RequestMapping("/mechanic") public class MechanicController { + private static final Logger logger = LogManager.getLogger(MechanicController.class); private MechanicService mechanicService; @@ -29,16 +32,18 @@ public class MechanicController { @GetMapping public String index(@PageableDefault Pageable pageable, ModelMap modelMap) { - Page clientList = mechanicService.findAll(pageable); + Page mechanicList = mechanicService.findAll(pageable); + logger.trace("Request to open list page for Mechanics. Returning {} page.", () -> pageable.getPageNumber() + 1); - modelMap.addAttribute("mechanicList", clientList.getContent()); - modelMap.addAttribute("totalPages", clientList.getTotalPages()); + modelMap.addAttribute("mechanicList", mechanicList.getContent()); + modelMap.addAttribute("totalPages", mechanicList.getTotalPages()); return "mechanic/index"; } @GetMapping(value = "/create") public String create(Model model) { + logger.trace("Request to open create page for Mechanic."); model.addAttribute("mechanic", new Mechanic()); return "mechanic/edit"; @@ -46,41 +51,45 @@ public class MechanicController { @GetMapping(value = "/edit/{id}") public String edit(@PathVariable Long id, Model model) { - Optional clientOptional = mechanicService.findById(id); - if (clientOptional.isPresent()) { - model.addAttribute("mechanic", clientOptional.get()); + logger.trace("Request to open edit page for Mechanic[{}].", () -> id); + Optional mechanicOptional = mechanicService.findById(id); + if (mechanicOptional.isPresent()) { + model.addAttribute("mechanic", mechanicOptional.get()); return "mechanic/edit"; } else { - // TODO: need to show warning return "redirect:/mechanic"; } } @PostMapping(value = "/update/{id}") - public String update(@Valid Mechanic client, BindingResult bindingResult, @PathVariable long id) { + public String update(@Valid Mechanic mechanic, BindingResult bindingResult, @PathVariable long id) { + logger.trace("Request to save {}.", () -> mechanic); if (bindingResult.hasErrors()) { - client.setId(id); // why should we do this? + logger.trace("{} has validation {} errors and won't be saved.", () -> mechanic, bindingResult::getErrorCount); + mechanic.setId(id); // why should we do this? return "mechanic/edit"; } - mechanicService.save(client); + mechanicService.save(mechanic); return "redirect:/mechanic"; } @PostMapping(value = "/create") - public String save(@Valid Mechanic client, BindingResult bindingResult) { + public String save(@Valid Mechanic mechanic, BindingResult bindingResult) { + logger.trace("Request to create {}.", () -> mechanic); if (bindingResult.hasErrors()) { + logger.trace("{} has validation {} errors and won't be created.", () -> mechanic, bindingResult::getErrorCount); return "mechanic/edit"; } - mechanicService.save(client); + mechanicService.save(mechanic); return "redirect:/mechanic"; } @DeleteMapping(value = "/delete/{id}") public ResponseEntity delete(@PathVariable Long id) { + logger.trace("Request to delete Mechanic[{}].", () -> id); boolean deleteSuccess = mechanicService.deleteMechanicById(id); - if (deleteSuccess) { return ResponseEntity.ok().build(); } else { @@ -90,6 +99,7 @@ public class MechanicController { @GetMapping(value = "/statistics/{id}") public String statistics(@PathVariable Long id, Model model) { + logger.trace("Request to open statistics for Mechanic[{}].", () -> id); Map mechanicStatistics = mechanicService.getOrderStatistics(id); model.addAttribute("statistics", mechanicStatistics); diff --git a/src/main/java/com/github/prominence/carrepair/controller/OrderController.java b/src/main/java/com/github/prominence/carrepair/controller/OrderController.java index 911cae4..79afcc6 100644 --- a/src/main/java/com/github/prominence/carrepair/controller/OrderController.java +++ b/src/main/java/com/github/prominence/carrepair/controller/OrderController.java @@ -4,6 +4,8 @@ import com.github.prominence.carrepair.enums.OrderStatus; import com.github.prominence.carrepair.model.Order; import com.github.prominence.carrepair.repository.spec.OrderSpecifications; import com.github.prominence.carrepair.service.OrderService; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; @@ -19,6 +21,7 @@ import java.util.Optional; @Controller @RequestMapping(value = "/order") public class OrderController { + private static final Logger logger = LogManager.getLogger(OrderController.class); private OrderService orderService; @@ -30,6 +33,7 @@ public class OrderController { public String index(@PageableDefault Pageable pageable, @RequestParam(required = false) String client, @RequestParam(required = false) String description, @RequestParam(required = false) OrderStatus orderStatus, ModelMap modelMap) { Page orderList = orderService.findAll(OrderSpecifications.search(client, description, orderStatus), pageable); + logger.trace("Request to open list page for Orders. Returning {} page.", () -> pageable.getPageNumber() + 1); modelMap.addAttribute("orderList", orderList.getContent()); modelMap.addAttribute("totalPages", orderList.getTotalPages()); @@ -40,6 +44,7 @@ public class OrderController { @GetMapping(value = "/create") public String create(Model model) { + logger.trace("Request to open create page for Order."); model.addAttribute("order", new Order()); model.addAttribute("orderStatuses", OrderStatus.values()); @@ -48,21 +53,23 @@ public class OrderController { @GetMapping(value = "/edit/{id}") public String edit(@PathVariable Long id, Model model) { + logger.trace("Request to open edit page for Order[{}].", () -> id); Optional orderOptional = orderService.findById(id); if (orderOptional.isPresent()) { model.addAttribute("order", orderOptional.get()); model.addAttribute("orderStatuses", OrderStatus.values()); return "order/edit"; } else { - // TODO: need to show warning return "redirect:/order"; } } @PostMapping(value = "/update/{id}") public String update(Order order, BindingResult bindingResult, @PathVariable long id, Long clientId, Long mechanicId, Model model) { + logger.trace("Request to save {}.", () -> order); orderService.fetchNestedObjectsAndValidate(order, clientId, mechanicId, bindingResult); if (bindingResult.hasErrors()) { + logger.trace("{} has validation {} errors and won't be saved.", () -> order, bindingResult::getErrorCount); order.setId(id); // why should we do this? model.addAttribute("orderStatuses", OrderStatus.values()); return "order/edit"; @@ -74,8 +81,10 @@ public class OrderController { @PostMapping(value = "/create") public String save(Order order, BindingResult bindingResult, Long clientId, Long mechanicId, Model model) { + logger.trace("Request to create {}.", () -> order); orderService.fetchNestedObjectsAndValidate(order, clientId, mechanicId, bindingResult); if (bindingResult.hasErrors()) { + logger.trace("{} has validation {} errors and won't be created.", () -> order, bindingResult::getErrorCount); model.addAttribute("orderStatuses", OrderStatus.values()); return "order/edit"; } @@ -86,8 +95,8 @@ public class OrderController { @DeleteMapping(value = "/delete/{id}") public ResponseEntity delete(@PathVariable Long id) { + logger.trace("Request to delete Order[{}].", () -> id); boolean deleteSuccess = orderService.deleteOrderById(id); - if (deleteSuccess) { return ResponseEntity.ok().build(); } else { diff --git a/src/main/java/com/github/prominence/carrepair/demo/DemoDataPopulator.java b/src/main/java/com/github/prominence/carrepair/demo/DemoDataPopulator.java index a4f093e..1a02dfe 100644 --- a/src/main/java/com/github/prominence/carrepair/demo/DemoDataPopulator.java +++ b/src/main/java/com/github/prominence/carrepair/demo/DemoDataPopulator.java @@ -9,6 +9,8 @@ import com.github.prominence.carrepair.service.ClientService; import com.github.prominence.carrepair.service.MechanicService; import com.github.prominence.carrepair.service.OrderService; import org.apache.commons.lang3.RandomUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.springframework.boot.CommandLineRunner; import org.springframework.context.annotation.Bean; import org.springframework.data.domain.PageRequest; @@ -26,8 +28,10 @@ import java.util.stream.Stream; @Component public class DemoDataPopulator { private static final int COUNT = 100; + private static final int DEFAULT_PAGE_SIZE = 10; + private final Logger logger = LogManager.getLogger(DemoDataPopulator.class); - private Faker faker = new Faker(); + private final Faker faker = new Faker(); @Bean public CommandLineRunner clientDemoData(ClientService clientService) { @@ -37,9 +41,9 @@ public class DemoDataPopulator { client.setLastName(faker.name().lastName()); client.setMiddleName(faker.name().username()); client.setPhoneNo(faker.phoneNumber().phoneNumber()); - System.out.println(client); // demo output return client; }).limit(COUNT).collect(Collectors.toList()); + logger.info("[Demo Data] Populated {} clients.", demoClientList::size); return args -> demoClientList.forEach(clientService::save); } @@ -52,9 +56,9 @@ public class DemoDataPopulator { mechanic.setLastName(faker.name().lastName()); mechanic.setMiddleName(faker.name().username()); mechanic.setHourlyPayment(BigDecimal.valueOf(faker.number().randomDouble(3, 100, 999))); - System.out.println(mechanic); // demo output return mechanic; }).limit(COUNT).collect(Collectors.toList()); + logger.info("[Demo Data] Populated {} mechanics.", demoMechanicList::size); return args -> demoMechanicList.forEach(mechanicService::save); } @@ -80,22 +84,22 @@ public class DemoDataPopulator { final Client randomClient = clientListSlice.get(RandomUtils.nextInt(0, clientListSlice.size())); order.setClient(randomClient); - final List mechanicListSlise = mechanicService.findAll(getRandomPageable(mechanicsCount)).getContent(); - final Mechanic randomMechanic = mechanicListSlise.get(RandomUtils.nextInt(0, mechanicListSlise.size())); + final List mechanicListSlice = mechanicService.findAll(getRandomPageable(mechanicsCount)).getContent(); + final Mechanic randomMechanic = mechanicListSlice.get(RandomUtils.nextInt(0, mechanicListSlice.size())); order.setMechanic(randomMechanic); - System.out.println(order); // demo output return order; }).limit(COUNT).collect(Collectors.toList()); + logger.info("[Demo Data] Populated {} orders.", demoOrderList::size); return args -> demoOrderList.forEach(orderService::save); } private Pageable getRandomPageable(long totalRecords) { - final int size = 10; - final int totalPages = (int) (totalRecords / size); - - return PageRequest.of(RandomUtils.nextInt(0, totalPages), size); + final int totalPages = (int) (totalRecords / DEFAULT_PAGE_SIZE); + final PageRequest pageRequest = PageRequest.of(RandomUtils.nextInt(0, totalPages), DEFAULT_PAGE_SIZE); + logger.trace("[Demo Data] Random page: {}", () -> pageRequest); + return pageRequest; } } diff --git a/src/main/java/com/github/prominence/carrepair/formatter/CustomDateTimeFormatter.java b/src/main/java/com/github/prominence/carrepair/formatter/CustomDateTimeFormatter.java index 5f2ff72..b76fc99 100644 --- a/src/main/java/com/github/prominence/carrepair/formatter/CustomDateTimeFormatter.java +++ b/src/main/java/com/github/prominence/carrepair/formatter/CustomDateTimeFormatter.java @@ -1,5 +1,7 @@ package com.github.prominence.carrepair.formatter; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.springframework.format.Formatter; import org.springframework.stereotype.Component; @@ -10,13 +12,19 @@ import java.util.Locale; @Component public class CustomDateTimeFormatter implements Formatter { + private static final Logger logger = LogManager.getLogger(CustomDateTimeFormatter.class); + @Override public LocalDateTime parse(String text, Locale locale) throws ParseException { - return LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + final LocalDateTime parsedDateTime = LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + logger.trace("Parsing String[{}] to LocalDateTime instance: {}.", () -> text, () -> parsedDateTime); + return parsedDateTime; } @Override public String print(LocalDateTime object, Locale locale) { - return object.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + final String formattedString = object.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + logger.trace("Formatting LocalDateTime[{}] to String instance: {}.", () -> object, () -> formattedString); + return formattedString; } } diff --git a/src/main/java/com/github/prominence/carrepair/formatter/OrderStatusFormatter.java b/src/main/java/com/github/prominence/carrepair/formatter/OrderStatusFormatter.java index aa2b7ac..a99c4ae 100644 --- a/src/main/java/com/github/prominence/carrepair/formatter/OrderStatusFormatter.java +++ b/src/main/java/com/github/prominence/carrepair/formatter/OrderStatusFormatter.java @@ -2,6 +2,8 @@ package com.github.prominence.carrepair.formatter; import com.github.prominence.carrepair.enums.OrderStatus; import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.springframework.format.Formatter; import org.springframework.stereotype.Component; @@ -10,13 +12,19 @@ import java.util.Locale; @Component public class OrderStatusFormatter implements Formatter { + private static final Logger logger = LogManager.getLogger(OrderStatusFormatter.class); + @Override public OrderStatus parse(String text, Locale locale) throws ParseException { - return OrderStatus.valueOf(text.toUpperCase()); + final OrderStatus parsedOrderStatus = OrderStatus.valueOf(text.toUpperCase()); + logger.trace("Parsing String[{}] to OrderStatus instance: {}.", () -> text, () -> parsedOrderStatus); + return parsedOrderStatus; } @Override public String print(OrderStatus object, Locale locale) { - return StringUtils.capitalize(object.toString().toLowerCase()); + final String formattedOrderStatus = StringUtils.capitalize(object.toString().toLowerCase()); + logger.trace("Formatting OrderStatus[{}] to String instance: {}.", () -> object, () -> formattedOrderStatus); + return formattedOrderStatus; } } diff --git a/src/main/java/com/github/prominence/carrepair/repository/spec/OrderSpecifications.java b/src/main/java/com/github/prominence/carrepair/repository/spec/OrderSpecifications.java index 4200397..dfc446b 100644 --- a/src/main/java/com/github/prominence/carrepair/repository/spec/OrderSpecifications.java +++ b/src/main/java/com/github/prominence/carrepair/repository/spec/OrderSpecifications.java @@ -4,6 +4,8 @@ import com.github.prominence.carrepair.enums.OrderStatus; import com.github.prominence.carrepair.model.Client; import com.github.prominence.carrepair.model.Order; import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.springframework.data.jpa.domain.Specification; import org.springframework.lang.Nullable; @@ -13,8 +15,11 @@ import java.util.ArrayList; import java.util.List; public class OrderSpecifications { + private static final Logger logger = LogManager.getLogger(OrderSpecifications.class); public static Specification search(@Nullable String clientQuery, @Nullable String orderDescriptionQuery, @Nullable OrderStatus orderStatusQuery) { + logger.debug("Creating specification for order search. Params: clientQuery=[{}], orderDescriptionQuery=[{}], orderStatusQuery=[{}]", + () -> clientQuery, () -> orderDescriptionQuery, () -> orderStatusQuery); return (root, criteriaQuery, criteriaBuilder) -> { List predicates = new ArrayList<>(); if (!StringUtils.isEmpty(clientQuery)) { diff --git a/src/main/java/com/github/prominence/carrepair/service/ClientService.java b/src/main/java/com/github/prominence/carrepair/service/ClientService.java index d5e3494..df446b6 100644 --- a/src/main/java/com/github/prominence/carrepair/service/ClientService.java +++ b/src/main/java/com/github/prominence/carrepair/service/ClientService.java @@ -2,6 +2,8 @@ package com.github.prominence.carrepair.service; import com.github.prominence.carrepair.model.Client; import com.github.prominence.carrepair.repository.ClientRepository; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @@ -11,6 +13,7 @@ import java.util.Optional; @Service public class ClientService { + private static final Logger logger = LogManager.getLogger(ClientService.class); private ClientRepository clientRepository; @@ -19,31 +22,43 @@ public class ClientService { } public Page findAll(Pageable pageable) { - return clientRepository.findAll(pageable); + final Page clientPage = clientRepository.findAll(pageable); + logger.trace(clientPage); + return clientPage; } public Optional findById(Long id) { - return clientRepository.findById(id); + final Optional clientOptional = clientRepository.findById(id); + logger.debug("{} found by id={}", () -> clientOptional, () -> id); + return clientOptional; } public Client save(Client client) { - return clientRepository.save(client); + final Client clientToSave = clientRepository.save(client); + logger.trace("[{}] was saved.", () -> clientToSave); + return clientToSave; } public boolean deleteClientById(Long id) { try { clientRepository.deleteById(id); + logger.debug("Client[id={}] was deleted.", () -> id); return true; } catch (Exception e) { + logger.error("Client[id={}] wasn't deleted. Exception: {}", () -> id, e::getMessage); return false; } } public long getClientCount() { - return clientRepository.count(); + final long clientCount = clientRepository.count(); + logger.trace("Found {} clients.", () -> clientCount); + return clientCount; } public List searchByInitials(String query) { - return clientRepository.findAllByInitials(query); + final List allByInitials = clientRepository.findAllByInitials(query); + logger.debug("Found {} clients by initials: {}.", allByInitials::size, () -> query); + return allByInitials; } } diff --git a/src/main/java/com/github/prominence/carrepair/service/MechanicService.java b/src/main/java/com/github/prominence/carrepair/service/MechanicService.java index fda5746..db545b7 100644 --- a/src/main/java/com/github/prominence/carrepair/service/MechanicService.java +++ b/src/main/java/com/github/prominence/carrepair/service/MechanicService.java @@ -5,6 +5,8 @@ import com.github.prominence.carrepair.model.Mechanic; import com.github.prominence.carrepair.model.Order; import com.github.prominence.carrepair.repository.MechanicRepository; import com.github.prominence.carrepair.repository.OrderRepository; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @@ -16,6 +18,7 @@ import java.util.Optional; @Service public class MechanicService { + private static final Logger logger = LogManager.getLogger(MechanicService.class); private MechanicRepository mechanicRepository; private OrderRepository orderRepository; @@ -26,22 +29,30 @@ public class MechanicService { } public Page findAll(Pageable pageable) { - return mechanicRepository.findAll(pageable); + final Page mechanicPage = mechanicRepository.findAll(pageable); + logger.trace(mechanicPage); + return mechanicPage; } public Optional findById(Long id) { - return mechanicRepository.findById(id); + final Optional mechanicOptional = mechanicRepository.findById(id); + logger.debug("{} found by id={}", () -> mechanicOptional, () -> id); + return mechanicOptional; } public Mechanic save(Mechanic client) { - return mechanicRepository.save(client); + final Mechanic mechanicToSave = mechanicRepository.save(client); + logger.trace("[{}] was saved.", () -> mechanicToSave); + return mechanicToSave; } public boolean deleteMechanicById(Long id) { try { mechanicRepository.deleteById(id); + logger.debug("Mechanic[id={}] was deleted.", () -> id); return true; } catch (Exception e) { + logger.error("Mechanic[id={}] wasn't deleted. Exception: {}", () -> id, e::getMessage); return false; } } @@ -55,15 +66,20 @@ public class MechanicService { List mechanicOrders = orderRepository.findAllByMechanic_Id(mechanicId); mechanicOrders.forEach(order -> statistics.merge(order.getOrderStatus(), 1, Integer::sum)); + logger.trace("Mechanic statistics by ID={}: {}", () -> mechanicId, () -> statistics); return statistics; } public long getMechanicCount() { - return mechanicRepository.count(); + final long mechanicCount = mechanicRepository.count(); + logger.trace("Found {} mechanics.", () -> mechanicCount); + return mechanicCount; } public List searchByInitials(String query) { - return mechanicRepository.findAllByInitials(query); + final List allByInitials = mechanicRepository.findAllByInitials(query); + logger.debug("Found {} mechanics by initials: {}.", allByInitials::size, () -> query); + return allByInitials; } } diff --git a/src/main/java/com/github/prominence/carrepair/service/OrderService.java b/src/main/java/com/github/prominence/carrepair/service/OrderService.java index 9662dbc..5a39bab 100644 --- a/src/main/java/com/github/prominence/carrepair/service/OrderService.java +++ b/src/main/java/com/github/prominence/carrepair/service/OrderService.java @@ -3,6 +3,8 @@ package com.github.prominence.carrepair.service; import com.github.prominence.carrepair.model.Order; import com.github.prominence.carrepair.repository.OrderRepository; import com.github.prominence.carrepair.validation.OrderValidator; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; @@ -14,6 +16,7 @@ import java.util.Optional; @Service public class OrderService { + private static final Logger logger = LogManager.getLogger(OrderService.class); private OrderRepository orderRepository; @@ -31,35 +34,47 @@ public class OrderService { } public Page findAll(Specification specification, Pageable pageable) { - return orderRepository.findAll(specification, pageable); + final Page orderPage = orderRepository.findAll(specification, pageable); + logger.trace(orderPage); + return orderPage; } public Optional findById(Long id) { - return orderRepository.findById(id); + final Optional orderOptional = orderRepository.findById(id); + logger.debug("{} found by id={}", () -> orderOptional, () -> id); + return orderOptional; } - public Order save(Order client) { - return orderRepository.save(client); + public Order save(Order order) { + final Order orderToSave = orderRepository.save(order); + logger.trace("[{}] was saved.", () -> orderToSave); + return orderToSave; } public boolean deleteOrderById(Long id) { try { orderRepository.deleteById(id); + logger.debug("Order[id={}] was deleted.", () -> id); return true; } catch (Exception e) { + logger.error("Order[id={}] wasn't deleted. Exception: {}", () -> id, e::getMessage); return false; } } public long getOrderCount() { - return orderRepository.count(); + final long orderCount = orderRepository.count(); + logger.trace("Found {} orders.", () -> orderCount); + return orderCount; } public void fetchNestedObjectsAndValidate(Order order, Long clientId, Long mechanicId, BindingResult bindingResult) { if (clientId != null) { + logger.trace("Fetching Client[{}] for {}.", () -> clientId, () -> order); clientService.findById(clientId).ifPresent(order::setClient); } if (mechanicId != null) { + logger.trace("Fetching Mechanic[{}] for {}.", () -> clientId, () -> order); mechanicService.findById(mechanicId).ifPresent(order::setMechanic); } smartValidator.validate(order, bindingResult); diff --git a/src/main/java/com/github/prominence/carrepair/validation/OrderValidator.java b/src/main/java/com/github/prominence/carrepair/validation/OrderValidator.java index ab2eb05..3d3511b 100644 --- a/src/main/java/com/github/prominence/carrepair/validation/OrderValidator.java +++ b/src/main/java/com/github/prominence/carrepair/validation/OrderValidator.java @@ -2,6 +2,8 @@ package com.github.prominence.carrepair.validation; import com.github.prominence.carrepair.enums.OrderStatus; import com.github.prominence.carrepair.model.Order; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.springframework.stereotype.Component; import org.springframework.validation.Errors; import org.springframework.validation.Validator; @@ -10,6 +12,8 @@ import java.time.LocalDateTime; @Component public class OrderValidator implements Validator { + private static final Logger logger = LogManager.getLogger(OrderValidator.class); + @Override public boolean supports(Class aClass) { return Order.class.isAssignableFrom(aClass); @@ -20,12 +24,16 @@ public class OrderValidator implements Validator { Order order = (Order) o; LocalDateTime finishedOn = order.getFinishedOn(); if (finishedOn != null) { - LocalDateTime startedOn = order.getCreatedOn(); - if (startedOn != null && order.getFinishedOn().isBefore(order.getCreatedOn())) { + LocalDateTime createdOn = order.getCreatedOn(); + if (createdOn != null && order.getFinishedOn().isBefore(order.getCreatedOn())) { + logger.debug("[{}] validation error: \"finishedOn\" value[{}] is before \"createdOn\"[{}].", + () -> order, () -> finishedOn, () -> createdOn); errors.rejectValue("finishedOn", "error.finishedOn.finishedBeforeStarted"); } if (order.getOrderStatus() != OrderStatus.ACCEPTED) { + logger.debug("[{}] validation error: \"finishedOn\" cannot be set for order in status differ from {}.", + () -> order, () -> OrderStatus.ACCEPTED); errors.rejectValue("finishedOn", "error.finishedOn.incompatibleStatus"); } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 151c6c9..c7c84fc 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -11,7 +11,7 @@ spring.datasource.password=carrepair # JPA / HIBERNATE # =============================== -spring.jpa.show-sql=true +spring.jpa.show-sql=false spring.jpa.hibernate.ddl-auto=validate spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect diff --git a/src/main/resources/log4j2.properties b/src/main/resources/log4j2.properties new file mode 100644 index 0000000..1988dc7 --- /dev/null +++ b/src/main/resources/log4j2.properties @@ -0,0 +1,23 @@ +name = LoggingsConfig +property.filename = logs +appenders = console, file + +appender.console.type = Console +appender.console.name = STDOUT +appender.console.layout.type = PatternLayout +appender.console.layout.pattern = [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n + +appender.file.type = File +appender.file.name = LOGFILE +appender.file.fileName=${filename}/application.log +appender.file.layout.type=PatternLayout +appender.file.layout.pattern=[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n + +loggers = base + +logger.base.name = com.github.prominence +logger.base.level = DEBUG + +rootLogger.level = info +rootLogger.appenderRefs = stdout +rootLogger.appenderRef.stdout.ref = STDOUT \ No newline at end of file diff --git a/src/main/resources/templates/home.html b/src/main/resources/templates/index.html similarity index 100% rename from src/main/resources/templates/home.html rename to src/main/resources/templates/index.html