├── .gitattributes
├── .gitignore
├── config.properties
├── pom.xml
└── src
├── main
├── java
│ └── victor
│ │ └── training
│ │ └── exceptions
│ │ ├── Biz.java
│ │ ├── Config.java
│ │ ├── GlobalExceptionHandler.java
│ │ ├── InProduction.java
│ │ ├── MyException.java
│ │ ├── SpringBoot.java
│ │ ├── Streams.java
│ │ └── model
│ │ ├── Customer.java
│ │ ├── MemberCard.java
│ │ └── Order.java
└── resources
│ ├── application.properties
│ ├── messages.properties
│ └── messages_RO.properties
└── test
└── java
└── victor
└── training
└── exceptions
└── BizTest.java
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Eclipse
2 | .project
3 | .classpath
4 | .settings/
5 | bin/
6 |
7 | # IntelliJ
8 | .idea
9 | *.ipr
10 | *.iml
11 | *.iws
12 |
13 | # NetBeans
14 | nb-configuration.xml
15 |
16 | # Visual Studio Code
17 | .vscode
18 | .factorypath
19 |
20 | # OSX
21 | .DS_Store
22 |
23 | # Vim
24 | *.swp
25 | *.swo
26 |
27 | # patch
28 | *.orig
29 | *.rej
30 |
31 | # Maven
32 | target/
33 | pom.xml.tag
34 | pom.xml.releaseBackup
35 | pom.xml.versionsBackup
36 | release.properties
37 | /app.log
38 | /app.log.*.gz
39 |
--------------------------------------------------------------------------------
/config.properties:
--------------------------------------------------------------------------------
1 | last.promo.date=xxx2021-01-30
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | victor.training
8 | exceptions-guide
9 | 1.0.0
10 |
11 |
12 | 15
13 |
14 |
15 |
16 |
17 | org.springframework.boot
18 | spring-boot-starter-web
19 |
20 |
21 | org.projectlombok
22 | lombok
23 |
24 | 1.18.16
25 |
26 |
27 | commons-io
28 | commons-io
29 | 2.0
30 |
31 |
32 | junit
33 | junit
34 | 4.10
35 |
36 |
37 | org.jooq
38 | jool
39 | 0.9.14
40 |
41 |
42 | io.vavr
43 | vavr
44 | 0.10.3
45 |
46 |
47 | commons-lang
48 | commons-lang
49 | 2.6
50 |
51 |
52 | org.springframework.boot
53 | spring-boot-devtools
54 | runtime
55 | true
56 |
57 |
58 |
59 |
60 |
61 |
62 | spring-boot-dependencies
63 | org.springframework.boot
64 | import
65 | pom
66 | 2.3.4.RELEASE
67 |
68 |
69 |
70 |
71 |
72 |
73 | org.springframework.boot
74 | spring-boot-maven-plugin
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/src/main/java/victor/training/exceptions/Biz.java:
--------------------------------------------------------------------------------
1 | package victor.training.exceptions;
2 |
3 | import org.apache.commons.lang.time.DateUtils;
4 | import org.springframework.stereotype.Service;
5 | import victor.training.exceptions.model.Customer;
6 | import victor.training.exceptions.model.Order;
7 |
8 | import java.text.ParseException;
9 | import java.util.Date;
10 |
11 | /**
12 | * @author Bill G.
13 | */
14 | @Service
15 | public class Biz {
16 |
17 | public void applyDiscount(Order order, Customer customer) {
18 | if (order.getOfferDate().before(Config.getLastPromoDate())
19 | && customer.getMemberCard().isPresent()) {
20 | System.out.println("APPLYING DISCOUNT");
21 | order.setPrice(order.getPrice() * (100 - 2 * customer.getMemberCard().get().getFidelityDiscount()) / 100);
22 | } else {
23 | System.out.println("NO DISCOUNT");
24 | }
25 | }
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/src/main/java/victor/training/exceptions/Config.java:
--------------------------------------------------------------------------------
1 | package victor.training.exceptions;
2 |
3 | import lombok.SneakyThrows;
4 | import org.springframework.stereotype.Service;
5 | import victor.training.exceptions.MyException.ErrorCode;
6 |
7 | import java.io.*;
8 | import java.text.ParseException;
9 | import java.text.SimpleDateFormat;
10 | import java.util.Date;
11 | import java.util.Properties;
12 |
13 | /**
14 | * @author Alan T.
15 | */
16 | public class Config {
17 |
18 |
19 | @SneakyThrows
20 | public static Date getLastPromoDate() {
21 | // try {
22 | long userInputUsefulToReportBackToHim = 1;
23 |
24 | // try {
25 | Properties properties = new Properties();
26 | try (Reader reader = new FileReader("config.properties")) {
27 | properties.load(reader);
28 | }
29 | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
30 | return format.parse(properties.getProperty("last.promo.date"));
31 | // } catch (IOException | ParseException e) {
32 | // throw new RuntimeException(e);
33 | // }
34 | // } catch (Throwable var8) {
35 | // throw var8;
36 | // }
37 | }
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/victor/training/exceptions/GlobalExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package victor.training.exceptions;
2 |
3 | import lombok.RequiredArgsConstructor;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.context.MessageSource;
6 | import org.springframework.web.bind.annotation.ExceptionHandler;
7 | import org.springframework.web.bind.annotation.ResponseStatus;
8 | import org.springframework.web.bind.annotation.RestControllerAdvice;
9 | import victor.training.exceptions.MyException.ErrorCode;
10 |
11 | import javax.servlet.http.HttpServletRequest;
12 |
13 | @Slf4j
14 | @RequiredArgsConstructor
15 | @RestControllerAdvice
16 | public class GlobalExceptionHandler {
17 |
18 | @ExceptionHandler(Exception.class)
19 | @ResponseStatus
20 | public String handleRuntime(Exception e, HttpServletRequest request) {
21 | String userMessage = messageSource.getMessage(ErrorCode.GENERAL.name(), null, request.getLocale());
22 | log.error("Unexpected " + userMessage, e);
23 | return userMessage;
24 | }
25 | private final MessageSource messageSource;
26 |
27 | @ExceptionHandler(MyException.class)
28 | @ResponseStatus
29 | public String handleMyException(MyException e, HttpServletRequest request) {
30 | String userMessage = messageSource.getMessage(e.getCode().name(), e.getParams(), request.getLocale());
31 | log.error("Unexpected " + userMessage, e);
32 | return userMessage;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/victor/training/exceptions/InProduction.java:
--------------------------------------------------------------------------------
1 | package victor.training.exceptions;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import victor.training.exceptions.model.Customer;
5 | import victor.training.exceptions.model.MemberCard;
6 | import victor.training.exceptions.model.Order;
7 |
8 | import java.util.Date;
9 |
10 | @Slf4j
11 | public class InProduction {
12 |
13 | private static Biz biz = new Biz();
14 |
15 | public static void main(String[] args) {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/victor/training/exceptions/MyException.java:
--------------------------------------------------------------------------------
1 | package victor.training.exceptions;
2 |
3 |
4 | class MyRecoverableException extends MyException {
5 |
6 | public MyRecoverableException(Throwable cause, Object... params) {
7 | super(ErrorCode.RECOVERABLE_ERR1, cause, params);
8 | }
9 | }
10 |
11 | public class MyException extends RuntimeException {
12 | public enum ErrorCode {
13 | GENERAL,
14 | RECOVERABLE_ERR1,
15 | BAD_CONFIG;
16 |
17 | }
18 | private final ErrorCode code;
19 |
20 | private final Object[] params;
21 | public MyException(ErrorCode code, Throwable cause, Object... params) {
22 | super(cause);
23 | this.code = code;
24 | this.params = params;
25 | }
26 |
27 | public MyException(Exception cause) {
28 | this(ErrorCode.GENERAL, cause);
29 | }
30 |
31 | public Object[] getParams() {
32 | return params;
33 | }
34 |
35 | public ErrorCode getCode() {
36 | return code;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/victor/training/exceptions/SpringBoot.java:
--------------------------------------------------------------------------------
1 | package victor.training.exceptions;
2 |
3 | import lombok.RequiredArgsConstructor;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.boot.SpringApplication;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 | import org.springframework.web.bind.annotation.GetMapping;
8 | import org.springframework.web.bind.annotation.RestController;
9 | import victor.training.exceptions.model.Customer;
10 | import victor.training.exceptions.model.MemberCard;
11 | import victor.training.exceptions.model.Order;
12 |
13 | import java.util.Date;
14 |
15 |
16 | @SpringBootApplication
17 | @Slf4j
18 | @RequiredArgsConstructor
19 | @RestController
20 | public class SpringBoot {
21 | public static void main(String[] args) {
22 | SpringApplication.run(SpringBoot.class, args);
23 | }
24 | private final Biz biz;
25 |
26 | @GetMapping
27 | public void exceptional() {
28 | Order order = new Order(null).setPrice(1000);
29 |
30 | biz.applyDiscount(order, new Customer().setMemberCard(new MemberCard()));
31 |
32 | System.out.println("Final Price " + order.getPrice());
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/victor/training/exceptions/Streams.java:
--------------------------------------------------------------------------------
1 | package victor.training.exceptions;
2 |
3 | import io.vavr.control.Try;
4 | import org.jooq.lambda.Unchecked;
5 |
6 | import java.text.SimpleDateFormat;
7 | import java.util.Date;
8 | import java.util.List;
9 | import java.util.function.Function;
10 |
11 | import static java.util.Arrays.asList;
12 | import static java.util.stream.Collectors.toList;
13 |
14 | public class Streams {
15 |
16 | public static void main(String[] args) {
17 | List dateList = asList("2020-10-11", "2020-nov-12", "2020-xxx12-01");
18 | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
19 |
20 | // TODO parse and print all dates
21 |
22 | // List dates = dateList.stream().map(Unchecked.function(format::parse)).collect(toList());
23 |
24 |
25 | List> tries = dateList.stream().map(s -> Try.of(() -> format.parse(s))).collect(toList());
26 |
27 | if (tries.stream().mapToInt(t->t.isSuccess()?1:0).average().getAsDouble() > .5) {
28 | List dates1 = tries.stream().filter(Try::isSuccess).map(Try::get).collect(toList());
29 | System.out.println(dates1);
30 | }
31 |
32 |
33 | }
34 |
35 | // private static Function wrapEx(ThrowingFunction f) {
36 | // return t -> {
37 | // try {
38 | // return f.apply(t);
39 | // } catch (Throwable throwable) {
40 | // throw new RuntimeException(throwable);
41 | // }
42 | // };
43 | // }
44 | //
45 | // interface ThrowingFunction {
46 | // R apply(T t) throws Throwable;
47 | // }
48 |
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/victor/training/exceptions/model/Customer.java:
--------------------------------------------------------------------------------
1 | package victor.training.exceptions.model;
2 |
3 | import java.util.Optional;
4 |
5 | import static java.util.Optional.ofNullable;
6 |
7 | public class Customer {
8 | private String name;
9 | private MemberCard memberCard;
10 |
11 | public Optional getMemberCard() {
12 | return ofNullable(memberCard);
13 | }
14 |
15 | public Customer setMemberCard(MemberCard memberCard) {
16 | this.memberCard = memberCard;
17 | return this;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/victor/training/exceptions/model/MemberCard.java:
--------------------------------------------------------------------------------
1 | package victor.training.exceptions.model;
2 |
3 | public class MemberCard {
4 | private int fidelityDiscount = 1;
5 |
6 | public int getFidelityDiscount() {
7 | return fidelityDiscount;
8 | }
9 |
10 | public MemberCard setFidelityDiscount(int fidelityDiscount) {
11 | this.fidelityDiscount = fidelityDiscount;
12 | return this;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/victor/training/exceptions/model/Order.java:
--------------------------------------------------------------------------------
1 | package victor.training.exceptions.model;
2 |
3 | import java.util.Date;
4 | import java.util.Objects;
5 |
6 | import static java.util.Objects.requireNonNull;
7 |
8 | public class Order {
9 | private int price;
10 | private Date offerDate;
11 |
12 | public Order(Date offerDate) {
13 | this.offerDate = requireNonNull(offerDate);
14 | }
15 |
16 | public int getPrice() {
17 | return price;
18 | }
19 |
20 | public Order setPrice(int price) {
21 | this.price = price;
22 | return this;
23 | }
24 |
25 | public Date getOfferDate() {
26 | return offerDate;
27 | }
28 |
29 | public Order setOfferDate(Date offerDate) {
30 | this.offerDate = requireNonNull(offerDate);
31 | return this;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | logging.file.name=app.log
--------------------------------------------------------------------------------
/src/main/resources/messages.properties:
--------------------------------------------------------------------------------
1 | GENERAL=Internal Error. Please check the logs.
2 | BAD_CONFIG=Bad {0} app config
--------------------------------------------------------------------------------
/src/main/resources/messages_RO.properties:
--------------------------------------------------------------------------------
1 | GENERAL=E Romania. Mai crapa. Vezi logu.
2 | BAD_CONFIG=Varza configuratie
--------------------------------------------------------------------------------
/src/test/java/victor/training/exceptions/BizTest.java:
--------------------------------------------------------------------------------
1 | package victor.training.exceptions;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 | import victor.training.exceptions.model.Customer;
6 | import victor.training.exceptions.model.MemberCard;
7 | import victor.training.exceptions.model.Order;
8 |
9 | import java.util.Date;
10 |
11 | import static org.junit.Assert.assertEquals;
12 |
13 | public class BizTest {
14 | @Test
15 | public void test() {
16 | System.setProperty("last.promo.date", "2021-02-30");
17 | Biz biz = new Biz();
18 |
19 | Customer customer = new Customer()
20 | .setMemberCard(new MemberCard()
21 | .setFidelityDiscount(2));
22 | Order order = new Order(new Date())
23 | .setPrice(1000);
24 |
25 | biz.applyDiscount(order, customer);
26 | System.out.println("Final Price in tests: " + order.getPrice());
27 | assertEquals(960, order.getPrice());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------