From 9fa6ad816703350bd04877cd59e463919ceded71 Mon Sep 17 00:00:00 2001 From: nkashlev Date: Wed, 24 Jan 2024 21:31:26 +0300 Subject: [PATCH 01/15] Prepare to HW0 --- .../javawebinar/topjava/model/UserMeal.java | 29 ++++++++++++++ .../topjava/model/UserMealWithExcess.java | 30 ++++++++++++++ .../ru/javawebinar/topjava/util/TimeUtil.java | 9 +++++ .../topjava/util/UserMealsUtil.java | 39 +++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 src/main/java/ru/javawebinar/topjava/model/UserMeal.java create mode 100644 src/main/java/ru/javawebinar/topjava/model/UserMealWithExcess.java create mode 100644 src/main/java/ru/javawebinar/topjava/util/TimeUtil.java create mode 100644 src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java diff --git a/src/main/java/ru/javawebinar/topjava/model/UserMeal.java b/src/main/java/ru/javawebinar/topjava/model/UserMeal.java new file mode 100644 index 000000000000..d8f91b127f6a --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/model/UserMeal.java @@ -0,0 +1,29 @@ +package ru.javawebinar.topjava.model; + +import java.time.LocalDateTime; + +public class UserMeal { + private final LocalDateTime dateTime; + + private final String description; + + private final int calories; + + public UserMeal(LocalDateTime dateTime, String description, int calories) { + this.dateTime = dateTime; + this.description = description; + this.calories = calories; + } + + public LocalDateTime getDateTime() { + return dateTime; + } + + public String getDescription() { + return description; + } + + public int getCalories() { + return calories; + } +} diff --git a/src/main/java/ru/javawebinar/topjava/model/UserMealWithExcess.java b/src/main/java/ru/javawebinar/topjava/model/UserMealWithExcess.java new file mode 100644 index 000000000000..d0aa431a35d9 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/model/UserMealWithExcess.java @@ -0,0 +1,30 @@ +package ru.javawebinar.topjava.model; + +import java.time.LocalDateTime; + +public class UserMealWithExcess { + private final LocalDateTime dateTime; + + private final String description; + + private final int calories; + + private final boolean excess; + + public UserMealWithExcess(LocalDateTime dateTime, String description, int calories, boolean excess) { + this.dateTime = dateTime; + this.description = description; + this.calories = calories; + this.excess = excess; + } + + @Override + public String toString() { + return "UserMealWithExcess{" + + "dateTime=" + dateTime + + ", description='" + description + '\'' + + ", calories=" + calories + + ", excess=" + excess + + '}'; + } +} diff --git a/src/main/java/ru/javawebinar/topjava/util/TimeUtil.java b/src/main/java/ru/javawebinar/topjava/util/TimeUtil.java new file mode 100644 index 000000000000..0ebfdb5fcdcb --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/util/TimeUtil.java @@ -0,0 +1,9 @@ +package ru.javawebinar.topjava.util; + +import java.time.LocalTime; + +public class TimeUtil { + public static boolean isBetweenHalfOpen(LocalTime lt, LocalTime startTime, LocalTime endTime) { + return lt.compareTo(startTime) >= 0 && lt.compareTo(endTime) < 0; + } +} diff --git a/src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java b/src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java new file mode 100644 index 000000000000..3c171b4a5972 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java @@ -0,0 +1,39 @@ +package ru.javawebinar.topjava.util; + +import ru.javawebinar.topjava.model.UserMeal; +import ru.javawebinar.topjava.model.UserMealWithExcess; + +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.Month; +import java.util.Arrays; +import java.util.List; + +public class UserMealsUtil { + public static void main(String[] args) { + List meals = Arrays.asList( + new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 30, 10, 0), "Завтрак", 500), + new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 30, 13, 0), "Обед", 1000), + new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 30, 20, 0), "Ужин", 500), + new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 31, 0, 0), "Еда на граничное значение", 100), + new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 31, 10, 0), "Завтрак", 1000), + new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 31, 13, 0), "Обед", 500), + new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 31, 20, 0), "Ужин", 410) + ); + + List mealsTo = filteredByCycles(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000); + mealsTo.forEach(System.out::println); + +// System.out.println(filteredByStreams(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000)); + } + + public static List filteredByCycles(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + // TODO return filtered list with excess. Implement by cycles + return null; + } + + public static List filteredByStreams(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + // TODO Implement by streams + return null; + } +} From 02fa55e01c22a8ee05ddb6884412cb22eccdbdd6 Mon Sep 17 00:00:00 2001 From: nkashlev Date: Thu, 1 Feb 2024 19:43:43 +0300 Subject: [PATCH 02/15] 1_0_fix_rename --- pom.xml | 4 +- .../java/ru/javawebinar/topjava/Main.java | 2 +- .../model/{UserMeal.java => Meal.java} | 4 +- .../{UserMealWithExcess.java => MealTo.java} | 6 +-- .../javawebinar/topjava/util/MealsUtil.java | 39 +++++++++++++++++++ .../topjava/util/UserMealsUtil.java | 39 ------------------- 6 files changed, 47 insertions(+), 47 deletions(-) rename src/main/java/ru/javawebinar/topjava/model/{UserMeal.java => Meal.java} (83%) rename src/main/java/ru/javawebinar/topjava/model/{UserMealWithExcess.java => MealTo.java} (77%) create mode 100644 src/main/java/ru/javawebinar/topjava/util/MealsUtil.java delete mode 100644 src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java diff --git a/pom.xml b/pom.xml index 0b1c2896da5b..2f53120afdf2 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ 1.0-SNAPSHOT Calories Management - http://topjava.herokuapp.com/ + https://javaops-demo.ru/topjava 1.8 @@ -24,7 +24,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.12.1 ${java.version} ${java.version} diff --git a/src/main/java/ru/javawebinar/topjava/Main.java b/src/main/java/ru/javawebinar/topjava/Main.java index c2f9cc618f7c..723742bacade 100644 --- a/src/main/java/ru/javawebinar/topjava/Main.java +++ b/src/main/java/ru/javawebinar/topjava/Main.java @@ -1,7 +1,7 @@ package ru.javawebinar.topjava; /** - * @see Demo application + * @see Demo application * @see Initial project */ public class Main { diff --git a/src/main/java/ru/javawebinar/topjava/model/UserMeal.java b/src/main/java/ru/javawebinar/topjava/model/Meal.java similarity index 83% rename from src/main/java/ru/javawebinar/topjava/model/UserMeal.java rename to src/main/java/ru/javawebinar/topjava/model/Meal.java index d8f91b127f6a..f546cef0f74a 100644 --- a/src/main/java/ru/javawebinar/topjava/model/UserMeal.java +++ b/src/main/java/ru/javawebinar/topjava/model/Meal.java @@ -2,14 +2,14 @@ import java.time.LocalDateTime; -public class UserMeal { +public class Meal { private final LocalDateTime dateTime; private final String description; private final int calories; - public UserMeal(LocalDateTime dateTime, String description, int calories) { + public Meal(LocalDateTime dateTime, String description, int calories) { this.dateTime = dateTime; this.description = description; this.calories = calories; diff --git a/src/main/java/ru/javawebinar/topjava/model/UserMealWithExcess.java b/src/main/java/ru/javawebinar/topjava/model/MealTo.java similarity index 77% rename from src/main/java/ru/javawebinar/topjava/model/UserMealWithExcess.java rename to src/main/java/ru/javawebinar/topjava/model/MealTo.java index d0aa431a35d9..07f04f8dbb9f 100644 --- a/src/main/java/ru/javawebinar/topjava/model/UserMealWithExcess.java +++ b/src/main/java/ru/javawebinar/topjava/model/MealTo.java @@ -2,7 +2,7 @@ import java.time.LocalDateTime; -public class UserMealWithExcess { +public class MealTo { private final LocalDateTime dateTime; private final String description; @@ -11,7 +11,7 @@ public class UserMealWithExcess { private final boolean excess; - public UserMealWithExcess(LocalDateTime dateTime, String description, int calories, boolean excess) { + public MealTo(LocalDateTime dateTime, String description, int calories, boolean excess) { this.dateTime = dateTime; this.description = description; this.calories = calories; @@ -20,7 +20,7 @@ public UserMealWithExcess(LocalDateTime dateTime, String description, int calori @Override public String toString() { - return "UserMealWithExcess{" + + return "MealTo{" + "dateTime=" + dateTime + ", description='" + description + '\'' + ", calories=" + calories + diff --git a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java new file mode 100644 index 000000000000..bb5ddbf5ccc5 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java @@ -0,0 +1,39 @@ +package ru.javawebinar.topjava.util; + +import ru.javawebinar.topjava.model.Meal; +import ru.javawebinar.topjava.model.MealTo; + +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.Month; +import java.util.Arrays; +import java.util.List; + +public class MealsUtil { + public static void main(String[] args) { + List meals = Arrays.asList( + new Meal(LocalDateTime.of(2020, Month.JANUARY, 30, 10, 0), "Завтрак", 500), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 30, 13, 0), "Обед", 1000), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 30, 20, 0), "Ужин", 500), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 0, 0), "Еда на граничное значение", 100), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 10, 0), "Завтрак", 1000), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 13, 0), "Обед", 500), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 20, 0), "Ужин", 410) + ); + + List mealsTo = filteredByCycles(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000); + mealsTo.forEach(System.out::println); + +// System.out.println(filteredByStreams(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000)); + } + + public static List filteredByCycles(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + // TODO return filtered list with excess. Implement by cycles + return null; + } + + public static List filteredByStreams(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + // TODO Implement by streams + return null; + } +} diff --git a/src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java b/src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java deleted file mode 100644 index 3c171b4a5972..000000000000 --- a/src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java +++ /dev/null @@ -1,39 +0,0 @@ -package ru.javawebinar.topjava.util; - -import ru.javawebinar.topjava.model.UserMeal; -import ru.javawebinar.topjava.model.UserMealWithExcess; - -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.Month; -import java.util.Arrays; -import java.util.List; - -public class UserMealsUtil { - public static void main(String[] args) { - List meals = Arrays.asList( - new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 30, 10, 0), "Завтрак", 500), - new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 30, 13, 0), "Обед", 1000), - new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 30, 20, 0), "Ужин", 500), - new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 31, 0, 0), "Еда на граничное значение", 100), - new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 31, 10, 0), "Завтрак", 1000), - new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 31, 13, 0), "Обед", 500), - new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 31, 20, 0), "Ужин", 410) - ); - - List mealsTo = filteredByCycles(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000); - mealsTo.forEach(System.out::println); - -// System.out.println(filteredByStreams(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000)); - } - - public static List filteredByCycles(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - // TODO return filtered list with excess. Implement by cycles - return null; - } - - public static List filteredByStreams(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - // TODO Implement by streams - return null; - } -} From a6493aadfa07265220fb84b76be99a7ec625f9f3 Mon Sep 17 00:00:00 2001 From: nkashlev Date: Thu, 1 Feb 2024 19:54:47 +0300 Subject: [PATCH 03/15] 1_1_HW0_streams --- .../ru/javawebinar/topjava/model/Meal.java | 10 +++++++ .../javawebinar/topjava/util/MealsUtil.java | 26 ++++++++++++------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/main/java/ru/javawebinar/topjava/model/Meal.java b/src/main/java/ru/javawebinar/topjava/model/Meal.java index f546cef0f74a..943ff5cd59fa 100644 --- a/src/main/java/ru/javawebinar/topjava/model/Meal.java +++ b/src/main/java/ru/javawebinar/topjava/model/Meal.java @@ -1,6 +1,8 @@ package ru.javawebinar.topjava.model; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; public class Meal { private final LocalDateTime dateTime; @@ -26,4 +28,12 @@ public String getDescription() { public int getCalories() { return calories; } + + public LocalDate getDate() { + return dateTime.toLocalDate(); + } + + public LocalTime getTime() { + return dateTime.toLocalTime(); + } } diff --git a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java index bb5ddbf5ccc5..c29e1fbbb077 100644 --- a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java +++ b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java @@ -3,11 +3,14 @@ import ru.javawebinar.topjava.model.Meal; import ru.javawebinar.topjava.model.MealTo; +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; public class MealsUtil { public static void main(String[] args) { @@ -21,19 +24,24 @@ public static void main(String[] args) { new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 20, 0), "Ужин", 410) ); - List mealsTo = filteredByCycles(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000); + List mealsTo = filteredByStreams(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000); mealsTo.forEach(System.out::println); - -// System.out.println(filteredByStreams(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000)); } - public static List filteredByCycles(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - // TODO return filtered list with excess. Implement by cycles - return null; + public static List filteredByStreams(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + Map caloriesSumByDate = meals.stream() + .collect( + Collectors.groupingBy(Meal::getDate, Collectors.summingInt(Meal::getCalories)) +// Collectors.toMap(Meal::getDate, Meal::getCalories, Integer::sum) + ); + + return meals.stream() + .filter(meal -> TimeUtil.isBetweenHalfOpen(meal.getTime(), startTime, endTime)) + .map(meal -> createTo(meal, caloriesSumByDate.get(meal.getDate()) > caloriesPerDay)) + .collect(Collectors.toList()); } - public static List filteredByStreams(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - // TODO Implement by streams - return null; + private static MealTo createTo(Meal meal, boolean excess) { + return new MealTo(meal.getDateTime(), meal.getDescription(), meal.getCalories(), excess); } } From 6315c773a46e738cb84e48ad1b8e7566eb8ed61a Mon Sep 17 00:00:00 2001 From: nkashlev Date: Thu, 1 Feb 2024 20:48:31 +0300 Subject: [PATCH 04/15] 1_2_war --- pom.xml | 9 +++++++-- src/main/webapp/WEB-INF/web.xml | 8 ++++++++ src/main/webapp/index.html | 9 +++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 src/main/webapp/WEB-INF/web.xml create mode 100644 src/main/webapp/index.html diff --git a/pom.xml b/pom.xml index 2f53120afdf2..ef6776d9d258 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ ru.javawebinar topjava - jar + war 1.0-SNAPSHOT @@ -19,8 +19,13 @@ topjava - install + package + + org.apache.maven.plugins + maven-war-plugin + 3.4.0 + org.apache.maven.plugins maven-compiler-plugin diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000000..abe697960203 --- /dev/null +++ b/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,8 @@ + + + TopJava + diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html new file mode 100644 index 000000000000..615f6db51dc8 --- /dev/null +++ b/src/main/webapp/index.html @@ -0,0 +1,9 @@ + + + + Java Enterprise (Topjava) + + +

Проект Java Enterprise (Topjava)

+ + From 66a65fd2bf30801ead4dcefba7238248888544b6 Mon Sep 17 00:00:00 2001 From: nkashlev Date: Thu, 1 Feb 2024 21:35:58 +0300 Subject: [PATCH 05/15] 1_3_servlet_api --- pom.xml | 7 ++++++- .../ru/javawebinar/topjava/web/UserServlet.java | 16 ++++++++++++++++ src/main/webapp/WEB-INF/web.xml | 10 ++++++++++ src/main/webapp/index.html | 4 ++++ src/main/webapp/users.jsp | 11 +++++++++++ 5 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/main/java/ru/javawebinar/topjava/web/UserServlet.java create mode 100644 src/main/webapp/users.jsp diff --git a/pom.xml b/pom.xml index ef6776d9d258..3a123e8e33cf 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,6 @@ UTF-8 UTF-8
- topjava package @@ -39,6 +38,12 @@ + + javax.servlet + javax.servlet-api + 4.0.1 + provided + diff --git a/src/main/java/ru/javawebinar/topjava/web/UserServlet.java b/src/main/java/ru/javawebinar/topjava/web/UserServlet.java new file mode 100644 index 000000000000..dcbb1c294f06 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/web/UserServlet.java @@ -0,0 +1,16 @@ +package ru.javawebinar.topjava.web; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.io.IOException; + +public class UserServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + request.getRequestDispatcher("/users.jsp").forward(request, response); + } +} diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index abe697960203..e576c30a3642 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -5,4 +5,14 @@ version="4.0"> TopJava + + + userServlet + ru.javawebinar.topjava.web.UserServlet + 0 + + + userServlet + /users + diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html index 615f6db51dc8..921d3b47281d 100644 --- a/src/main/webapp/index.html +++ b/src/main/webapp/index.html @@ -5,5 +5,9 @@

Проект Java Enterprise (Topjava)

+
+ diff --git a/src/main/webapp/users.jsp b/src/main/webapp/users.jsp new file mode 100644 index 000000000000..650c8dda479c --- /dev/null +++ b/src/main/webapp/users.jsp @@ -0,0 +1,11 @@ +<%@ page contentType="text/html;charset=UTF-8" %> + + + Users + + +

Home

+
+

Users

+ + \ No newline at end of file From 60f9038f4f6b2111cb8b4b91a8850f696a1a2519 Mon Sep 17 00:00:00 2001 From: nkashlev Date: Thu, 1 Feb 2024 21:39:23 +0300 Subject: [PATCH 06/15] 1_4_forward_to_redirect --- src/main/java/ru/javawebinar/topjava/web/UserServlet.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/ru/javawebinar/topjava/web/UserServlet.java b/src/main/java/ru/javawebinar/topjava/web/UserServlet.java index dcbb1c294f06..eac924a3841a 100644 --- a/src/main/java/ru/javawebinar/topjava/web/UserServlet.java +++ b/src/main/java/ru/javawebinar/topjava/web/UserServlet.java @@ -11,6 +11,7 @@ public class UserServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - request.getRequestDispatcher("/users.jsp").forward(request, response); +// request.getRequestDispatcher("/users.jsp").forward(request, response); + response.sendRedirect("users.jsp"); } } From c4904c0027a725e4aecdfb8971573fcdc0b73e89 Mon Sep 17 00:00:00 2001 From: nkashlev Date: Fri, 2 Feb 2024 19:17:35 +0300 Subject: [PATCH 07/15] 1_5_simple_logging --- pom.xml | 7 +++++++ src/main/java/ru/javawebinar/topjava/web/UserServlet.java | 8 +++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3a123e8e33cf..1f462ffcf54d 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,7 @@ 1.8 UTF-8 UTF-8 + 1.2.13 topjava @@ -44,6 +45,12 @@ 4.0.1 provided + + + ch.qos.logback + logback-classic + ${logback.version} + diff --git a/src/main/java/ru/javawebinar/topjava/web/UserServlet.java b/src/main/java/ru/javawebinar/topjava/web/UserServlet.java index eac924a3841a..ef52d67576c0 100644 --- a/src/main/java/ru/javawebinar/topjava/web/UserServlet.java +++ b/src/main/java/ru/javawebinar/topjava/web/UserServlet.java @@ -1,16 +1,22 @@ package ru.javawebinar.topjava.web; +import org.slf4j.Logger; + import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - import java.io.IOException; +import static org.slf4j.LoggerFactory.getLogger; + public class UserServlet extends HttpServlet { + private static final Logger log = getLogger(UserServlet.class); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + log.debug("redirect to users"); + // request.getRequestDispatcher("/users.jsp").forward(request, response); response.sendRedirect("users.jsp"); } From 311bab14a6066bce4e70f12a83cb7b069e13648a Mon Sep 17 00:00:00 2001 From: nkashlev Date: Fri, 2 Feb 2024 19:43:22 +0300 Subject: [PATCH 08/15] 1_6_logging_config --- pom.xml | 8 ++++++++ src/main/resources/logback.xml | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 src/main/resources/logback.xml diff --git a/pom.xml b/pom.xml index 1f462ffcf54d..f5bdbd417db0 100644 --- a/pom.xml +++ b/pom.xml @@ -16,6 +16,7 @@ UTF-8 UTF-8 1.2.13 + 1.7.36 topjava @@ -46,10 +47,17 @@ provided + + org.slf4j + slf4j-api + ${slf4j.version} + + ch.qos.logback logback-classic ${logback.version} + runtime diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 000000000000..bdf004d037fb --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,29 @@ + + + + + + + + ${TOPJAVA_ROOT}/log/topjava.log + + + UTF-8 + %date %-5level %logger{0} [%file:%line] %msg%n + + + + + + UTF-8 + %-5level %logger{0} [%file:%line] %msg%n + + + + + + + + + + \ No newline at end of file From 1acfd095e1b3a3a039d747f799405a0eb1afa839 Mon Sep 17 00:00:00 2001 From: nkashlev Date: Thu, 8 Feb 2024 21:33:25 +0300 Subject: [PATCH 09/15] 2_1_HW1 --- pom.xml | 6 +++ .../java/ru/javawebinar/topjava/Main.java | 11 ----- .../ru/javawebinar/topjava/model/MealTo.java | 16 +++++++ .../topjava/util/DateTimeUtil.java | 18 +++++++ .../javawebinar/topjava/util/MealsUtil.java | 36 ++++++++------ .../ru/javawebinar/topjava/util/TimeUtil.java | 9 ---- .../javawebinar/topjava/web/MealServlet.java | 22 +++++++++ .../javawebinar/topjava/web/UserServlet.java | 6 +-- src/main/webapp/WEB-INF/tld/functions.tld | 16 +++++++ src/main/webapp/WEB-INF/web.xml | 10 ++++ src/main/webapp/index.html | 1 + src/main/webapp/meals.jsp | 48 +++++++++++++++++++ 12 files changed, 160 insertions(+), 39 deletions(-) delete mode 100644 src/main/java/ru/javawebinar/topjava/Main.java create mode 100644 src/main/java/ru/javawebinar/topjava/util/DateTimeUtil.java delete mode 100644 src/main/java/ru/javawebinar/topjava/util/TimeUtil.java create mode 100644 src/main/java/ru/javawebinar/topjava/web/MealServlet.java create mode 100644 src/main/webapp/WEB-INF/tld/functions.tld create mode 100644 src/main/webapp/meals.jsp diff --git a/pom.xml b/pom.xml index f5bdbd417db0..fe435b13646b 100644 --- a/pom.xml +++ b/pom.xml @@ -59,6 +59,12 @@ ${logback.version} runtime + + + javax.servlet + jstl + 1.2 + diff --git a/src/main/java/ru/javawebinar/topjava/Main.java b/src/main/java/ru/javawebinar/topjava/Main.java deleted file mode 100644 index 723742bacade..000000000000 --- a/src/main/java/ru/javawebinar/topjava/Main.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.javawebinar.topjava; - -/** - * @see Demo application - * @see Initial project - */ -public class Main { - public static void main(String[] args) { - System.out.format("Hello TopJava Enterprise!"); - } -} diff --git a/src/main/java/ru/javawebinar/topjava/model/MealTo.java b/src/main/java/ru/javawebinar/topjava/model/MealTo.java index 07f04f8dbb9f..800b1fcbb5c3 100644 --- a/src/main/java/ru/javawebinar/topjava/model/MealTo.java +++ b/src/main/java/ru/javawebinar/topjava/model/MealTo.java @@ -18,6 +18,22 @@ public MealTo(LocalDateTime dateTime, String description, int calories, boolean this.excess = excess; } + public LocalDateTime getDateTime() { + return dateTime; + } + + public String getDescription() { + return description; + } + + public int getCalories() { + return calories; + } + + public boolean isExcess() { + return excess; + } + @Override public String toString() { return "MealTo{" + diff --git a/src/main/java/ru/javawebinar/topjava/util/DateTimeUtil.java b/src/main/java/ru/javawebinar/topjava/util/DateTimeUtil.java new file mode 100644 index 000000000000..3f23f83fde65 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/util/DateTimeUtil.java @@ -0,0 +1,18 @@ +package ru.javawebinar.topjava.util; + +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +public class DateTimeUtil { + private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + + public static boolean isBetweenHalfOpen(LocalTime lt, LocalTime startTime, LocalTime endTime) { + return lt.compareTo(startTime) >= 0 && lt.compareTo(endTime) < 0; + } + + public static String toString(LocalDateTime ldt) { + return ldt == null ? "" : ldt.format(DATE_TIME_FORMATTER); + } +} + diff --git a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java index c29e1fbbb077..ac9c815959c5 100644 --- a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java +++ b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java @@ -10,25 +10,31 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.function.Predicate; import java.util.stream.Collectors; public class MealsUtil { - public static void main(String[] args) { - List meals = Arrays.asList( - new Meal(LocalDateTime.of(2020, Month.JANUARY, 30, 10, 0), "Завтрак", 500), - new Meal(LocalDateTime.of(2020, Month.JANUARY, 30, 13, 0), "Обед", 1000), - new Meal(LocalDateTime.of(2020, Month.JANUARY, 30, 20, 0), "Ужин", 500), - new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 0, 0), "Еда на граничное значение", 100), - new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 10, 0), "Завтрак", 1000), - new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 13, 0), "Обед", 500), - new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 20, 0), "Ужин", 410) - ); - - List mealsTo = filteredByStreams(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000); - mealsTo.forEach(System.out::println); + public static final int DEFAULT_CALORIES_PER_DAY = 2000; + + public static final List meals = Arrays.asList( + new Meal(LocalDateTime.of(2020, Month.JANUARY, 30, 10, 0), "Завтрак", 500), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 30, 13, 0), "Обед", 1000), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 30, 20, 0), "Ужин", 500), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 0, 0), "Еда на граничное значение", 100), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 10, 0), "Завтрак", 1000), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 13, 0), "Обед", 500), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 20, 0), "Ужин", 410) + ); + + public static List getTos(List meals, int caloriesPerDay) { + return filterByPredicate(meals, caloriesPerDay, meal -> true); + } + + public static List getFilteredTos(List meals, int caloriesPerDay, LocalTime startTime, LocalTime endTime) { + return filterByPredicate(meals, caloriesPerDay, meal -> DateTimeUtil.isBetweenHalfOpen(meal.getTime(), startTime, endTime)); } - public static List filteredByStreams(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + private static List filterByPredicate(List meals, int caloriesPerDay, Predicate filter) { Map caloriesSumByDate = meals.stream() .collect( Collectors.groupingBy(Meal::getDate, Collectors.summingInt(Meal::getCalories)) @@ -36,7 +42,7 @@ public static List filteredByStreams(List meals, LocalTime startTi ); return meals.stream() - .filter(meal -> TimeUtil.isBetweenHalfOpen(meal.getTime(), startTime, endTime)) + .filter(filter) .map(meal -> createTo(meal, caloriesSumByDate.get(meal.getDate()) > caloriesPerDay)) .collect(Collectors.toList()); } diff --git a/src/main/java/ru/javawebinar/topjava/util/TimeUtil.java b/src/main/java/ru/javawebinar/topjava/util/TimeUtil.java deleted file mode 100644 index 0ebfdb5fcdcb..000000000000 --- a/src/main/java/ru/javawebinar/topjava/util/TimeUtil.java +++ /dev/null @@ -1,9 +0,0 @@ -package ru.javawebinar.topjava.util; - -import java.time.LocalTime; - -public class TimeUtil { - public static boolean isBetweenHalfOpen(LocalTime lt, LocalTime startTime, LocalTime endTime) { - return lt.compareTo(startTime) >= 0 && lt.compareTo(endTime) < 0; - } -} diff --git a/src/main/java/ru/javawebinar/topjava/web/MealServlet.java b/src/main/java/ru/javawebinar/topjava/web/MealServlet.java new file mode 100644 index 000000000000..8b47dd35450e --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/web/MealServlet.java @@ -0,0 +1,22 @@ +package ru.javawebinar.topjava.web; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.javawebinar.topjava.util.MealsUtil; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class MealServlet extends HttpServlet { + private static final Logger log = LoggerFactory.getLogger(MealServlet.class); + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + log.info("forward to meals"); + request.setAttribute("meals", MealsUtil.getTos(MealsUtil.meals, MealsUtil.DEFAULT_CALORIES_PER_DAY)); + request.getRequestDispatcher("/meals.jsp").forward(request, response); + } +} diff --git a/src/main/java/ru/javawebinar/topjava/web/UserServlet.java b/src/main/java/ru/javawebinar/topjava/web/UserServlet.java index ef52d67576c0..f6cf12e69976 100644 --- a/src/main/java/ru/javawebinar/topjava/web/UserServlet.java +++ b/src/main/java/ru/javawebinar/topjava/web/UserServlet.java @@ -15,9 +15,7 @@ public class UserServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - log.debug("redirect to users"); - -// request.getRequestDispatcher("/users.jsp").forward(request, response); - response.sendRedirect("users.jsp"); + log.debug("forward to users"); + request.getRequestDispatcher("/users.jsp").forward(request, response); } } diff --git a/src/main/webapp/WEB-INF/tld/functions.tld b/src/main/webapp/WEB-INF/tld/functions.tld new file mode 100644 index 000000000000..d138fecdbfb5 --- /dev/null +++ b/src/main/webapp/WEB-INF/tld/functions.tld @@ -0,0 +1,16 @@ + + + + 1.0 + functions + http://topjava.javawebinar.ru/functions + + + formatDateTime + ru.javawebinar.topjava.util.DateTimeUtil + java.lang.String toString(java.time.LocalDateTime) + + diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index e576c30a3642..0ac5a7610ed4 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -15,4 +15,14 @@ userServlet /users + + + mealServlet + ru.javawebinar.topjava.web.MealServlet + 0 + + + mealServlet + /meals + diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html index 921d3b47281d..714683bd3856 100644 --- a/src/main/webapp/index.html +++ b/src/main/webapp/index.html @@ -8,6 +8,7 @@

Проект
  • Users
  • +
  • Meals
  • diff --git a/src/main/webapp/meals.jsp b/src/main/webapp/meals.jsp new file mode 100644 index 000000000000..adc5a2c94ce4 --- /dev/null +++ b/src/main/webapp/meals.jsp @@ -0,0 +1,48 @@ +<%@ page contentType="text/html;charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="fn" uri="http://topjava.javawebinar.ru/functions" %> +<%--<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>--%> + + + Meal list + + + +
    +

    Home

    +
    +

    Meals

    + + + + + + + + + + + + + + + + +
    DateDescriptionCalories
    + <%--${meal.dateTime.toLocalDate()} ${meal.dateTime.toLocalTime()}--%> + <%--<%=TimeUtil.toString(meal.getDateTime())%>--%> + <%--${fn:replace(meal.dateTime, 'T', ' ')}--%> + ${fn:formatDateTime(meal.dateTime)} + ${meal.description}${meal.calories}
    +
    + + \ No newline at end of file From 3428e0d7ad140f19ece7e9265e61cb051d040f72 Mon Sep 17 00:00:00 2001 From: nkashlev Date: Thu, 8 Feb 2024 21:36:06 +0300 Subject: [PATCH 10/15] 2_2_HW1_optional --- .../ru/javawebinar/topjava/model/Meal.java | 29 +++++++++ .../ru/javawebinar/topjava/model/MealTo.java | 12 +++- .../repository/InMemoryMealRepository.java | 45 ++++++++++++++ .../topjava/repository/MealRepository.java | 18 ++++++ .../javawebinar/topjava/util/MealsUtil.java | 9 +-- .../javawebinar/topjava/web/MealServlet.java | 61 ++++++++++++++++++- src/main/webapp/mealForm.jsp | 51 ++++++++++++++++ src/main/webapp/meals.jsp | 6 ++ 8 files changed, 222 insertions(+), 9 deletions(-) create mode 100644 src/main/java/ru/javawebinar/topjava/repository/InMemoryMealRepository.java create mode 100644 src/main/java/ru/javawebinar/topjava/repository/MealRepository.java create mode 100644 src/main/webapp/mealForm.jsp diff --git a/src/main/java/ru/javawebinar/topjava/model/Meal.java b/src/main/java/ru/javawebinar/topjava/model/Meal.java index 943ff5cd59fa..3abbee42511e 100644 --- a/src/main/java/ru/javawebinar/topjava/model/Meal.java +++ b/src/main/java/ru/javawebinar/topjava/model/Meal.java @@ -5,6 +5,8 @@ import java.time.LocalTime; public class Meal { + private Integer id; + private final LocalDateTime dateTime; private final String description; @@ -12,11 +14,24 @@ public class Meal { private final int calories; public Meal(LocalDateTime dateTime, String description, int calories) { + this(null, dateTime, description, calories); + } + + public Meal(Integer id, LocalDateTime dateTime, String description, int calories) { + this.id = id; this.dateTime = dateTime; this.description = description; this.calories = calories; } + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public LocalDateTime getDateTime() { return dateTime; } @@ -36,4 +51,18 @@ public LocalDate getDate() { public LocalTime getTime() { return dateTime.toLocalTime(); } + + public boolean isNew() { + return id == null; + } + + @Override + public String toString() { + return "Meal{" + + "id=" + id + + ", dateTime=" + dateTime + + ", description='" + description + '\'' + + ", calories=" + calories + + '}'; + } } diff --git a/src/main/java/ru/javawebinar/topjava/model/MealTo.java b/src/main/java/ru/javawebinar/topjava/model/MealTo.java index 800b1fcbb5c3..01b3a5fdaad1 100644 --- a/src/main/java/ru/javawebinar/topjava/model/MealTo.java +++ b/src/main/java/ru/javawebinar/topjava/model/MealTo.java @@ -3,6 +3,8 @@ import java.time.LocalDateTime; public class MealTo { + private final Integer id; + private final LocalDateTime dateTime; private final String description; @@ -11,13 +13,18 @@ public class MealTo { private final boolean excess; - public MealTo(LocalDateTime dateTime, String description, int calories, boolean excess) { + public MealTo(Integer id, LocalDateTime dateTime, String description, int calories, boolean excess) { + this.id = id; this.dateTime = dateTime; this.description = description; this.calories = calories; this.excess = excess; } + public Integer getId() { + return id; + } + public LocalDateTime getDateTime() { return dateTime; } @@ -37,7 +44,8 @@ public boolean isExcess() { @Override public String toString() { return "MealTo{" + - "dateTime=" + dateTime + + "id=" + id + + ", dateTime=" + dateTime + ", description='" + description + '\'' + ", calories=" + calories + ", excess=" + excess + diff --git a/src/main/java/ru/javawebinar/topjava/repository/InMemoryMealRepository.java b/src/main/java/ru/javawebinar/topjava/repository/InMemoryMealRepository.java new file mode 100644 index 000000000000..ad6669056a4b --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/repository/InMemoryMealRepository.java @@ -0,0 +1,45 @@ +package ru.javawebinar.topjava.repository; + +import ru.javawebinar.topjava.model.Meal; +import ru.javawebinar.topjava.util.MealsUtil; + +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +public class InMemoryMealRepository implements MealRepository { + private final Map repository = new ConcurrentHashMap<>(); + private final AtomicInteger counter = new AtomicInteger(0); + + { + MealsUtil.meals.forEach(this::save); + } + + @Override + public Meal save(Meal meal) { + if (meal.isNew()) { + meal.setId(counter.incrementAndGet()); + repository.put(meal.getId(), meal); + return meal; + } + // handle case: update, but not present in storage + return repository.computeIfPresent(meal.getId(), (id, oldMeal) -> meal); + } + + @Override + public boolean delete(int id) { + return repository.remove(id) != null; + } + + @Override + public Meal get(int id) { + return repository.get(id); + } + + @Override + public Collection getAll() { + return repository.values(); + } +} + diff --git a/src/main/java/ru/javawebinar/topjava/repository/MealRepository.java b/src/main/java/ru/javawebinar/topjava/repository/MealRepository.java new file mode 100644 index 000000000000..2cb2aef8ba8d --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/repository/MealRepository.java @@ -0,0 +1,18 @@ +package ru.javawebinar.topjava.repository; + +import ru.javawebinar.topjava.model.Meal; + +import java.util.Collection; + +public interface MealRepository { + // null if not found, when updated + Meal save(Meal meal); + + // false if not found + boolean delete(int id); + + // null if not found + Meal get(int id); + + Collection getAll(); +} diff --git a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java index ac9c815959c5..8d940a63efa1 100644 --- a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java +++ b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java @@ -8,6 +8,7 @@ import java.time.LocalTime; import java.time.Month; import java.util.Arrays; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.function.Predicate; @@ -26,15 +27,15 @@ public class MealsUtil { new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 20, 0), "Ужин", 410) ); - public static List getTos(List meals, int caloriesPerDay) { + public static List getTos(Collection meals, int caloriesPerDay) { return filterByPredicate(meals, caloriesPerDay, meal -> true); } - public static List getFilteredTos(List meals, int caloriesPerDay, LocalTime startTime, LocalTime endTime) { + public static List getFilteredTos(Collection meals, int caloriesPerDay, LocalTime startTime, LocalTime endTime) { return filterByPredicate(meals, caloriesPerDay, meal -> DateTimeUtil.isBetweenHalfOpen(meal.getTime(), startTime, endTime)); } - private static List filterByPredicate(List meals, int caloriesPerDay, Predicate filter) { + private static List filterByPredicate(Collection meals, int caloriesPerDay, Predicate filter) { Map caloriesSumByDate = meals.stream() .collect( Collectors.groupingBy(Meal::getDate, Collectors.summingInt(Meal::getCalories)) @@ -48,6 +49,6 @@ private static List filterByPredicate(List meals, int caloriesPerD } private static MealTo createTo(Meal meal, boolean excess) { - return new MealTo(meal.getDateTime(), meal.getDescription(), meal.getCalories(), excess); + return new MealTo(meal.getId(), meal.getDateTime(), meal.getDescription(), meal.getCalories(), excess); } } diff --git a/src/main/java/ru/javawebinar/topjava/web/MealServlet.java b/src/main/java/ru/javawebinar/topjava/web/MealServlet.java index 8b47dd35450e..78d73c710e57 100644 --- a/src/main/java/ru/javawebinar/topjava/web/MealServlet.java +++ b/src/main/java/ru/javawebinar/topjava/web/MealServlet.java @@ -2,6 +2,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import ru.javawebinar.topjava.model.Meal; +import ru.javawebinar.topjava.repository.InMemoryMealRepository; +import ru.javawebinar.topjava.repository.MealRepository; import ru.javawebinar.topjava.util.MealsUtil; import javax.servlet.ServletException; @@ -9,14 +12,66 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.Objects; public class MealServlet extends HttpServlet { private static final Logger log = LoggerFactory.getLogger(MealServlet.class); + private MealRepository repository; + + @Override + public void init() { + repository = new InMemoryMealRepository(); + } + + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { + request.setCharacterEncoding("UTF-8"); + String id = request.getParameter("id"); + + Meal meal = new Meal(id.isEmpty() ? null : Integer.valueOf(id), + LocalDateTime.parse(request.getParameter("dateTime")), + request.getParameter("description"), + Integer.parseInt(request.getParameter("calories"))); + + log.info(meal.isNew() ? "Create {}" : "Update {}", meal); + repository.save(meal); + response.sendRedirect("meals"); + } + @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - log.info("forward to meals"); - request.setAttribute("meals", MealsUtil.getTos(MealsUtil.meals, MealsUtil.DEFAULT_CALORIES_PER_DAY)); - request.getRequestDispatcher("/meals.jsp").forward(request, response); + String action = request.getParameter("action"); + + switch (action == null ? "all" : action) { + case "delete": + int id = getId(request); + log.info("Delete id={}", id); + repository.delete(id); + response.sendRedirect("meals"); + break; + case "create": + case "update": + final Meal meal = "create".equals(action) ? + new Meal(LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES), "", 1000) : + repository.get(getId(request)); + request.setAttribute("meal", meal); + request.getRequestDispatcher("/mealForm.jsp").forward(request, response); + break; + case "all": + default: + log.info("getAll"); + request.setAttribute("meals", + MealsUtil.getTos(repository.getAll(), MealsUtil.DEFAULT_CALORIES_PER_DAY)); + request.getRequestDispatcher("/meals.jsp").forward(request, response); + break; + } + } + + private int getId(HttpServletRequest request) { + String paramId = Objects.requireNonNull(request.getParameter("id")); + return Integer.parseInt(paramId); } } diff --git a/src/main/webapp/mealForm.jsp b/src/main/webapp/mealForm.jsp new file mode 100644 index 000000000000..28f140b65fce --- /dev/null +++ b/src/main/webapp/mealForm.jsp @@ -0,0 +1,51 @@ +<%@ page contentType="text/html;charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + Meal + + + +
    +

    Home

    +
    +

    ${param.action == 'create' ? 'Create meal' : 'Edit meal'}

    + +
    + +
    +
    DateTime:
    +
    +
    +
    +
    Description:
    +
    +
    +
    +
    Calories:
    +
    +
    + + +
    +
    + + diff --git a/src/main/webapp/meals.jsp b/src/main/webapp/meals.jsp index adc5a2c94ce4..224d9876135b 100644 --- a/src/main/webapp/meals.jsp +++ b/src/main/webapp/meals.jsp @@ -21,12 +21,16 @@

    Home


    Meals

    + Add Meal +

    + + @@ -40,6 +44,8 @@ + +
    Date Description Calories
    ${meal.description} ${meal.calories}UpdateDelete
    From 8982abec05205ee3fbf2858660219f7c27ce8345 Mon Sep 17 00:00:00 2001 From: nkashlev Date: Sat, 10 Feb 2024 16:59:09 +0300 Subject: [PATCH 11/15] 2_3_app_layers --- .../topjava/model/AbstractBaseEntity.java | 26 ++++++ .../topjava/model/AbstractNamedEntity.java | 24 +++++ .../ru/javawebinar/topjava/model/Role.java | 6 ++ .../ru/javawebinar/topjava/model/User.java | 91 +++++++++++++++++++ .../topjava/repository/MealRepository.java | 8 +- .../topjava/repository/UserRepository.java | 21 +++++ .../topjava/service/MealService.java | 9 ++ .../topjava/service/UserService.java | 38 ++++++++ .../topjava/util/ValidationUtil.java | 43 +++++++++ .../util/exception/NotFoundException.java | 7 ++ .../javawebinar/topjava/web/SecurityUtil.java | 14 +++ .../topjava/web/meal/MealRestController.java | 8 ++ .../web/user/AbstractUserController.java | 49 ++++++++++ .../topjava/web/user/AdminRestController.java | 38 ++++++++ .../web/user/ProfileRestController.java | 20 ++++ 15 files changed, 399 insertions(+), 3 deletions(-) create mode 100644 src/main/java/ru/javawebinar/topjava/model/AbstractBaseEntity.java create mode 100644 src/main/java/ru/javawebinar/topjava/model/AbstractNamedEntity.java create mode 100644 src/main/java/ru/javawebinar/topjava/model/Role.java create mode 100644 src/main/java/ru/javawebinar/topjava/model/User.java create mode 100644 src/main/java/ru/javawebinar/topjava/repository/UserRepository.java create mode 100644 src/main/java/ru/javawebinar/topjava/service/MealService.java create mode 100644 src/main/java/ru/javawebinar/topjava/service/UserService.java create mode 100644 src/main/java/ru/javawebinar/topjava/util/ValidationUtil.java create mode 100644 src/main/java/ru/javawebinar/topjava/util/exception/NotFoundException.java create mode 100644 src/main/java/ru/javawebinar/topjava/web/SecurityUtil.java create mode 100644 src/main/java/ru/javawebinar/topjava/web/meal/MealRestController.java create mode 100644 src/main/java/ru/javawebinar/topjava/web/user/AbstractUserController.java create mode 100644 src/main/java/ru/javawebinar/topjava/web/user/AdminRestController.java create mode 100644 src/main/java/ru/javawebinar/topjava/web/user/ProfileRestController.java diff --git a/src/main/java/ru/javawebinar/topjava/model/AbstractBaseEntity.java b/src/main/java/ru/javawebinar/topjava/model/AbstractBaseEntity.java new file mode 100644 index 000000000000..8f27c902e047 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/model/AbstractBaseEntity.java @@ -0,0 +1,26 @@ +package ru.javawebinar.topjava.model; + +public abstract class AbstractBaseEntity { + protected Integer id; + + protected AbstractBaseEntity(Integer id) { + this.id = id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getId() { + return id; + } + + public boolean isNew() { + return this.id == null; + } + + @Override + public String toString() { + return getClass().getSimpleName() + ":" + id; + } +} \ No newline at end of file diff --git a/src/main/java/ru/javawebinar/topjava/model/AbstractNamedEntity.java b/src/main/java/ru/javawebinar/topjava/model/AbstractNamedEntity.java new file mode 100644 index 000000000000..2054a3d3cf9b --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/model/AbstractNamedEntity.java @@ -0,0 +1,24 @@ +package ru.javawebinar.topjava.model; + +public abstract class AbstractNamedEntity extends AbstractBaseEntity { + + protected String name; + + protected AbstractNamedEntity(Integer id, String name) { + super(id); + this.name = name; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + + @Override + public String toString() { + return super.toString() + '(' + name + ')'; + } +} \ No newline at end of file diff --git a/src/main/java/ru/javawebinar/topjava/model/Role.java b/src/main/java/ru/javawebinar/topjava/model/Role.java new file mode 100644 index 000000000000..acb7a276f6dc --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/model/Role.java @@ -0,0 +1,6 @@ +package ru.javawebinar.topjava.model; + +public enum Role { + USER, + ADMIN +} \ No newline at end of file diff --git a/src/main/java/ru/javawebinar/topjava/model/User.java b/src/main/java/ru/javawebinar/topjava/model/User.java new file mode 100644 index 000000000000..abafde5db5e1 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/model/User.java @@ -0,0 +1,91 @@ +package ru.javawebinar.topjava.model; + +import java.util.Date; +import java.util.EnumSet; +import java.util.Set; + +import static ru.javawebinar.topjava.util.MealsUtil.DEFAULT_CALORIES_PER_DAY; + +public class User extends AbstractNamedEntity { + + private String email; + + private String password; + + private boolean enabled; + + private Date registered = new Date(); + + private Set roles; + + private int caloriesPerDay; + + public User(Integer id, String name, String email, String password, Role role, Role... roles) { + this(id, name, email, password, DEFAULT_CALORIES_PER_DAY, true, EnumSet.of(role, roles)); + } + + public User(Integer id, String name, String email, String password, int caloriesPerDay, boolean enabled, Set roles) { + super(id, name); + this.email = email; + this.password = password; + this.caloriesPerDay = caloriesPerDay; + this.enabled = enabled; + this.roles = roles; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public void setPassword(String password) { + this.password = password; + } + + public Date getRegistered() { + return registered; + } + + public void setRegistered(Date registered) { + this.registered = registered; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public int getCaloriesPerDay() { + return caloriesPerDay; + } + + public void setCaloriesPerDay(int caloriesPerDay) { + this.caloriesPerDay = caloriesPerDay; + } + + public boolean isEnabled() { + return enabled; + } + + public Set getRoles() { + return roles; + } + + public String getPassword() { + return password; + } + + @Override + public String toString() { + return "User{" + + "id=" + id + + ", email=" + email + + ", name=" + name + + ", enabled=" + enabled + + ", roles=" + roles + + ", caloriesPerDay=" + caloriesPerDay + + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/ru/javawebinar/topjava/repository/MealRepository.java b/src/main/java/ru/javawebinar/topjava/repository/MealRepository.java index 2cb2aef8ba8d..675cdbb1bd38 100644 --- a/src/main/java/ru/javawebinar/topjava/repository/MealRepository.java +++ b/src/main/java/ru/javawebinar/topjava/repository/MealRepository.java @@ -4,15 +4,17 @@ import java.util.Collection; +// TODO add userId public interface MealRepository { - // null if not found, when updated + // null if updated meal does not belong to userId Meal save(Meal meal); - // false if not found + // false if meal does not belong to userId boolean delete(int id); - // null if not found + // null if meal does not belong to userId Meal get(int id); + // ORDERED dateTime desc Collection getAll(); } diff --git a/src/main/java/ru/javawebinar/topjava/repository/UserRepository.java b/src/main/java/ru/javawebinar/topjava/repository/UserRepository.java new file mode 100644 index 000000000000..138369789175 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/repository/UserRepository.java @@ -0,0 +1,21 @@ +package ru.javawebinar.topjava.repository; + +import ru.javawebinar.topjava.model.User; + +import java.util.List; + +public interface UserRepository { + // null if not found, when updated + User save(User user); + + // false if not found + boolean delete(int id); + + // null if not found + User get(int id); + + // null if not found + User getByEmail(String email); + + List getAll(); +} \ No newline at end of file diff --git a/src/main/java/ru/javawebinar/topjava/service/MealService.java b/src/main/java/ru/javawebinar/topjava/service/MealService.java new file mode 100644 index 000000000000..0dc4a43c394f --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/service/MealService.java @@ -0,0 +1,9 @@ +package ru.javawebinar.topjava.service; + +import ru.javawebinar.topjava.repository.MealRepository; + +public class MealService { + + private MealRepository repository; + +} \ No newline at end of file diff --git a/src/main/java/ru/javawebinar/topjava/service/UserService.java b/src/main/java/ru/javawebinar/topjava/service/UserService.java new file mode 100644 index 000000000000..b02082e352c4 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/service/UserService.java @@ -0,0 +1,38 @@ +package ru.javawebinar.topjava.service; + +import ru.javawebinar.topjava.model.User; +import ru.javawebinar.topjava.repository.UserRepository; + +import java.util.List; + +import static ru.javawebinar.topjava.util.ValidationUtil.checkNotFound; +import static ru.javawebinar.topjava.util.ValidationUtil.checkNotFoundWithId; + +public class UserService { + + private UserRepository repository; + + public User create(User user) { + return repository.save(user); + } + + public void delete(int id) { + checkNotFoundWithId(repository.delete(id), id); + } + + public User get(int id) { + return checkNotFoundWithId(repository.get(id), id); + } + + public User getByEmail(String email) { + return checkNotFound(repository.getByEmail(email), "email=" + email); + } + + public List getAll() { + return repository.getAll(); + } + + public void update(User user) { + checkNotFoundWithId(repository.save(user), user.getId()); + } +} \ No newline at end of file diff --git a/src/main/java/ru/javawebinar/topjava/util/ValidationUtil.java b/src/main/java/ru/javawebinar/topjava/util/ValidationUtil.java new file mode 100644 index 000000000000..971eb9c0c72b --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/util/ValidationUtil.java @@ -0,0 +1,43 @@ +package ru.javawebinar.topjava.util; + + +import ru.javawebinar.topjava.model.AbstractBaseEntity; +import ru.javawebinar.topjava.util.exception.NotFoundException; + +public class ValidationUtil { + + public static T checkNotFoundWithId(T object, int id) { + checkNotFoundWithId(object != null, id); + return object; + } + + public static void checkNotFoundWithId(boolean found, int id) { + checkNotFound(found, "id=" + id); + } + + public static T checkNotFound(T object, String msg) { + checkNotFound(object != null, msg); + return object; + } + + public static void checkNotFound(boolean found, String msg) { + if (!found) { + throw new NotFoundException("Not found entity with " + msg); + } + } + + public static void checkNew(AbstractBaseEntity entity) { + if (!entity.isNew()) { + throw new IllegalArgumentException(entity + " must be new (id=null)"); + } + } + + public static void assureIdConsistent(AbstractBaseEntity entity, int id) { +// conservative when you reply, but accept liberally (http://stackoverflow.com/a/32728226/548473) + if (entity.isNew()) { + entity.setId(id); + } else if (entity.getId() != id) { + throw new IllegalArgumentException(entity + " must be with id=" + id); + } + } +} \ No newline at end of file diff --git a/src/main/java/ru/javawebinar/topjava/util/exception/NotFoundException.java b/src/main/java/ru/javawebinar/topjava/util/exception/NotFoundException.java new file mode 100644 index 000000000000..f1e9b0e46376 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/util/exception/NotFoundException.java @@ -0,0 +1,7 @@ +package ru.javawebinar.topjava.util.exception; + +public class NotFoundException extends RuntimeException { + public NotFoundException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/src/main/java/ru/javawebinar/topjava/web/SecurityUtil.java b/src/main/java/ru/javawebinar/topjava/web/SecurityUtil.java new file mode 100644 index 000000000000..e78a4b284a9a --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/web/SecurityUtil.java @@ -0,0 +1,14 @@ +package ru.javawebinar.topjava.web; + +import static ru.javawebinar.topjava.util.MealsUtil.DEFAULT_CALORIES_PER_DAY; + +public class SecurityUtil { + + public static int authUserId() { + return 1; + } + + public static int authUserCaloriesPerDay() { + return DEFAULT_CALORIES_PER_DAY; + } +} \ No newline at end of file diff --git a/src/main/java/ru/javawebinar/topjava/web/meal/MealRestController.java b/src/main/java/ru/javawebinar/topjava/web/meal/MealRestController.java new file mode 100644 index 000000000000..ab4e8ea8bb8e --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/web/meal/MealRestController.java @@ -0,0 +1,8 @@ +package ru.javawebinar.topjava.web.meal; + +import ru.javawebinar.topjava.service.MealService; + +public class MealRestController { + private MealService service; + +} \ No newline at end of file diff --git a/src/main/java/ru/javawebinar/topjava/web/user/AbstractUserController.java b/src/main/java/ru/javawebinar/topjava/web/user/AbstractUserController.java new file mode 100644 index 000000000000..16a68259ec20 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/web/user/AbstractUserController.java @@ -0,0 +1,49 @@ +package ru.javawebinar.topjava.web.user; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.javawebinar.topjava.model.User; +import ru.javawebinar.topjava.service.UserService; + +import java.util.List; + +import static ru.javawebinar.topjava.util.ValidationUtil.assureIdConsistent; +import static ru.javawebinar.topjava.util.ValidationUtil.checkNew; + +public abstract class AbstractUserController { + protected final Logger log = LoggerFactory.getLogger(getClass()); + + private UserService service; + + public List getAll() { + log.info("getAll"); + return service.getAll(); + } + + public User get(int id) { + log.info("get {}", id); + return service.get(id); + } + + public User create(User user) { + log.info("create {}", user); + checkNew(user); + return service.create(user); + } + + public void delete(int id) { + log.info("delete {}", id); + service.delete(id); + } + + public void update(User user, int id) { + log.info("update {} with id={}", user, id); + assureIdConsistent(user, id); + service.update(user); + } + + public User getByMail(String email) { + log.info("getByEmail {}", email); + return service.getByEmail(email); + } +} \ No newline at end of file diff --git a/src/main/java/ru/javawebinar/topjava/web/user/AdminRestController.java b/src/main/java/ru/javawebinar/topjava/web/user/AdminRestController.java new file mode 100644 index 000000000000..ae3374468e41 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/web/user/AdminRestController.java @@ -0,0 +1,38 @@ +package ru.javawebinar.topjava.web.user; + +import ru.javawebinar.topjava.model.User; + +import java.util.List; + +public class AdminRestController extends AbstractUserController { + + @Override + public List getAll() { + return super.getAll(); + } + + @Override + public User get(int id) { + return super.get(id); + } + + @Override + public User create(User user) { + return super.create(user); + } + + @Override + public void delete(int id) { + super.delete(id); + } + + @Override + public void update(User user, int id) { + super.update(user, id); + } + + @Override + public User getByMail(String email) { + return super.getByMail(email); + } +} \ No newline at end of file diff --git a/src/main/java/ru/javawebinar/topjava/web/user/ProfileRestController.java b/src/main/java/ru/javawebinar/topjava/web/user/ProfileRestController.java new file mode 100644 index 000000000000..b5062e20bc90 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/web/user/ProfileRestController.java @@ -0,0 +1,20 @@ +package ru.javawebinar.topjava.web.user; + +import ru.javawebinar.topjava.model.User; + +import static ru.javawebinar.topjava.web.SecurityUtil.authUserId; + +public class ProfileRestController extends AbstractUserController { + + public User get() { + return super.get(authUserId()); + } + + public void delete() { + super.delete(authUserId()); + } + + public void update(User user) { + super.update(user, authUserId()); + } +} \ No newline at end of file From 0bc820e175d868f832ac46c2c39ccbaf8302a8cb Mon Sep 17 00:00:00 2001 From: nkashlev Date: Sat, 10 Feb 2024 17:20:37 +0300 Subject: [PATCH 12/15] 2_4_add_spring --- pom.xml | 15 ++++++++------- .../ru/javawebinar/topjava/model/User.java | 18 +++++++++++------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index fe435b13646b..f5c894572672 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ UTF-8 UTF-8 1.2.13 - 1.7.36 + 5.2.6.RELEASE topjava @@ -47,12 +47,6 @@ provided - - org.slf4j - slf4j-api - ${slf4j.version} - - ch.qos.logback logback-classic @@ -65,6 +59,13 @@ jstl 1.2 + + + org.springframework + spring-context + ${springcontext.version} + + diff --git a/src/main/java/ru/javawebinar/topjava/model/User.java b/src/main/java/ru/javawebinar/topjava/model/User.java index abafde5db5e1..0ec0257d923d 100644 --- a/src/main/java/ru/javawebinar/topjava/model/User.java +++ b/src/main/java/ru/javawebinar/topjava/model/User.java @@ -1,8 +1,8 @@ package ru.javawebinar.topjava.model; -import java.util.Date; -import java.util.EnumSet; -import java.util.Set; +import org.springframework.util.CollectionUtils; + +import java.util.*; import static ru.javawebinar.topjava.util.MealsUtil.DEFAULT_CALORIES_PER_DAY; @@ -20,17 +20,17 @@ public class User extends AbstractNamedEntity { private int caloriesPerDay; - public User(Integer id, String name, String email, String password, Role role, Role... roles) { - this(id, name, email, password, DEFAULT_CALORIES_PER_DAY, true, EnumSet.of(role, roles)); + public User(Integer id, String name, String email, String password, Role... roles) { + this(id, name, email, password, DEFAULT_CALORIES_PER_DAY, true, Arrays.asList(roles)); } - public User(Integer id, String name, String email, String password, int caloriesPerDay, boolean enabled, Set roles) { + public User(Integer id, String name, String email, String password, int caloriesPerDay, boolean enabled, Collection roles) { super(id, name); this.email = email; this.password = password; this.caloriesPerDay = caloriesPerDay; this.enabled = enabled; - this.roles = roles; + setRoles(roles); } public String getEmail() { @@ -73,6 +73,10 @@ public Set getRoles() { return roles; } + public void setRoles(Collection roles) { + this.roles = CollectionUtils.isEmpty(roles) ? EnumSet.noneOf(Role.class) : EnumSet.copyOf(roles); + } + public String getPassword() { return password; } From c0a57f535cf93281ddc535e29a00e3f7e14cb924 Mon Sep 17 00:00:00 2001 From: nkashlev Date: Sat, 10 Feb 2024 17:32:00 +0300 Subject: [PATCH 13/15] 2_5_add_spring_context --- pom.xml | 9 +++- .../ru/javawebinar/topjava/SpringMain.java | 19 ++++++++ .../InMemoryMealRepository.java | 3 +- .../inmemory/InMemoryUserRepository.java | 43 +++++++++++++++++++ .../javawebinar/topjava/web/MealServlet.java | 2 +- src/main/resources/spring/spring-app.xml | 7 +++ 6 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 src/main/java/ru/javawebinar/topjava/SpringMain.java rename src/main/java/ru/javawebinar/topjava/repository/{ => inmemory}/InMemoryMealRepository.java (91%) create mode 100644 src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryUserRepository.java create mode 100644 src/main/resources/spring/spring-app.xml diff --git a/pom.xml b/pom.xml index f5c894572672..6a3aca18373e 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,8 @@ UTF-8 UTF-8 1.2.13 - 5.2.6.RELEASE + 1.7.36 + 5.2.21.RELEASE topjava @@ -47,6 +48,12 @@ provided + + org.slf4j + slf4j-api + ${slf4j.version} + + ch.qos.logback logback-classic diff --git a/src/main/java/ru/javawebinar/topjava/SpringMain.java b/src/main/java/ru/javawebinar/topjava/SpringMain.java new file mode 100644 index 000000000000..e836531c305a --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/SpringMain.java @@ -0,0 +1,19 @@ +package ru.javawebinar.topjava; + +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import ru.javawebinar.topjava.repository.UserRepository; + +import java.util.Arrays; + +public class SpringMain { + public static void main(String[] args) { + ConfigurableApplicationContext appCtx = new ClassPathXmlApplicationContext("spring/spring-app.xml"); + System.out.println("Bean definition names: " + Arrays.toString(appCtx.getBeanDefinitionNames())); + +// UserRepository userRepository = (UserRepository) appCtx.getBean("inmemoryUserRepository"); + UserRepository userRepository = appCtx.getBean(UserRepository.class); + userRepository.getAll(); + appCtx.close(); + } +} diff --git a/src/main/java/ru/javawebinar/topjava/repository/InMemoryMealRepository.java b/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryMealRepository.java similarity index 91% rename from src/main/java/ru/javawebinar/topjava/repository/InMemoryMealRepository.java rename to src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryMealRepository.java index ad6669056a4b..3c7c9ff94dd2 100644 --- a/src/main/java/ru/javawebinar/topjava/repository/InMemoryMealRepository.java +++ b/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryMealRepository.java @@ -1,6 +1,7 @@ -package ru.javawebinar.topjava.repository; +package ru.javawebinar.topjava.repository.inmemory; import ru.javawebinar.topjava.model.Meal; +import ru.javawebinar.topjava.repository.MealRepository; import ru.javawebinar.topjava.util.MealsUtil; import java.util.Collection; diff --git a/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryUserRepository.java b/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryUserRepository.java new file mode 100644 index 000000000000..c9bcb8a4f289 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryUserRepository.java @@ -0,0 +1,43 @@ +package ru.javawebinar.topjava.repository.inmemory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.javawebinar.topjava.model.User; +import ru.javawebinar.topjava.repository.UserRepository; + +import java.util.Collections; +import java.util.List; + +public class InMemoryUserRepository implements UserRepository { + private static final Logger log = LoggerFactory.getLogger(InMemoryUserRepository.class); + + @Override + public boolean delete(int id) { + log.info("delete {}", id); + return true; + } + + @Override + public User save(User user) { + log.info("save {}", user); + return user; + } + + @Override + public User get(int id) { + log.info("get {}", id); + return null; + } + + @Override + public List getAll() { + log.info("getAll"); + return Collections.emptyList(); + } + + @Override + public User getByEmail(String email) { + log.info("getByEmail {}", email); + return null; + } +} diff --git a/src/main/java/ru/javawebinar/topjava/web/MealServlet.java b/src/main/java/ru/javawebinar/topjava/web/MealServlet.java index 78d73c710e57..7a0b8aed8ca7 100644 --- a/src/main/java/ru/javawebinar/topjava/web/MealServlet.java +++ b/src/main/java/ru/javawebinar/topjava/web/MealServlet.java @@ -3,8 +3,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ru.javawebinar.topjava.model.Meal; -import ru.javawebinar.topjava.repository.InMemoryMealRepository; import ru.javawebinar.topjava.repository.MealRepository; +import ru.javawebinar.topjava.repository.inmemory.InMemoryMealRepository; import ru.javawebinar.topjava.util.MealsUtil; import javax.servlet.ServletException; diff --git a/src/main/resources/spring/spring-app.xml b/src/main/resources/spring/spring-app.xml new file mode 100644 index 000000000000..3a32c66999dc --- /dev/null +++ b/src/main/resources/spring/spring-app.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file From 00e31fef4c1ad31769517052bb9a82e7be41fc2e Mon Sep 17 00:00:00 2001 From: nkashlev Date: Sat, 10 Feb 2024 17:54:37 +0300 Subject: [PATCH 14/15] 2_6_dependency_injection --- .../ru/javawebinar/topjava/SpringMain.java | 18 +++++++++++++----- .../inmemory/InMemoryMealRepository.java | 3 ++- .../inmemory/InMemoryUserRepository.java | 3 ++- .../topjava/service/MealService.java | 3 ++- .../topjava/service/UserService.java | 9 +++++++-- .../topjava/web/meal/MealRestController.java | 3 ++- .../web/user/AbstractUserController.java | 3 ++- .../topjava/web/user/AdminRestController.java | 3 ++- .../web/user/ProfileRestController.java | 3 ++- src/main/resources/spring/spring-app.xml | 13 +++++++++++-- 10 files changed, 45 insertions(+), 16 deletions(-) diff --git a/src/main/java/ru/javawebinar/topjava/SpringMain.java b/src/main/java/ru/javawebinar/topjava/SpringMain.java index e836531c305a..3bf57807ea3d 100644 --- a/src/main/java/ru/javawebinar/topjava/SpringMain.java +++ b/src/main/java/ru/javawebinar/topjava/SpringMain.java @@ -2,18 +2,26 @@ import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; +import ru.javawebinar.topjava.model.Role; +import ru.javawebinar.topjava.model.User; import ru.javawebinar.topjava.repository.UserRepository; +import ru.javawebinar.topjava.service.UserService; import java.util.Arrays; public class SpringMain { public static void main(String[] args) { - ConfigurableApplicationContext appCtx = new ClassPathXmlApplicationContext("spring/spring-app.xml"); - System.out.println("Bean definition names: " + Arrays.toString(appCtx.getBeanDefinitionNames())); + try ( + ConfigurableApplicationContext appCtx = new ClassPathXmlApplicationContext("spring/spring-app.xml")) { + System.out.println("Bean definition names: " + Arrays.toString(appCtx.getBeanDefinitionNames())); // UserRepository userRepository = (UserRepository) appCtx.getBean("inmemoryUserRepository"); - UserRepository userRepository = appCtx.getBean(UserRepository.class); - userRepository.getAll(); - appCtx.close(); + UserRepository userRepository = appCtx.getBean(UserRepository.class); + userRepository.getAll(); + + UserService userService = appCtx.getBean(UserService.class); + userService.create(new User(null, "userName", "email@mail.ru", "password", Role.ADMIN)); + } + } } diff --git a/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryMealRepository.java b/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryMealRepository.java index 3c7c9ff94dd2..4f0f52469f65 100644 --- a/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryMealRepository.java +++ b/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryMealRepository.java @@ -1,5 +1,6 @@ package ru.javawebinar.topjava.repository.inmemory; +import org.springframework.stereotype.Repository; import ru.javawebinar.topjava.model.Meal; import ru.javawebinar.topjava.repository.MealRepository; import ru.javawebinar.topjava.util.MealsUtil; @@ -8,7 +9,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; - +@Repository public class InMemoryMealRepository implements MealRepository { private final Map repository = new ConcurrentHashMap<>(); private final AtomicInteger counter = new AtomicInteger(0); diff --git a/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryUserRepository.java b/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryUserRepository.java index c9bcb8a4f289..24d2510f7616 100644 --- a/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryUserRepository.java +++ b/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryUserRepository.java @@ -2,12 +2,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Repository; import ru.javawebinar.topjava.model.User; import ru.javawebinar.topjava.repository.UserRepository; import java.util.Collections; import java.util.List; - +@Repository public class InMemoryUserRepository implements UserRepository { private static final Logger log = LoggerFactory.getLogger(InMemoryUserRepository.class); diff --git a/src/main/java/ru/javawebinar/topjava/service/MealService.java b/src/main/java/ru/javawebinar/topjava/service/MealService.java index 0dc4a43c394f..bc669b9b0228 100644 --- a/src/main/java/ru/javawebinar/topjava/service/MealService.java +++ b/src/main/java/ru/javawebinar/topjava/service/MealService.java @@ -1,7 +1,8 @@ package ru.javawebinar.topjava.service; +import org.springframework.stereotype.Service; import ru.javawebinar.topjava.repository.MealRepository; - +@Service public class MealService { private MealRepository repository; diff --git a/src/main/java/ru/javawebinar/topjava/service/UserService.java b/src/main/java/ru/javawebinar/topjava/service/UserService.java index b02082e352c4..d8f887b496fc 100644 --- a/src/main/java/ru/javawebinar/topjava/service/UserService.java +++ b/src/main/java/ru/javawebinar/topjava/service/UserService.java @@ -1,5 +1,6 @@ package ru.javawebinar.topjava.service; +import org.springframework.stereotype.Service; import ru.javawebinar.topjava.model.User; import ru.javawebinar.topjava.repository.UserRepository; @@ -7,10 +8,14 @@ import static ru.javawebinar.topjava.util.ValidationUtil.checkNotFound; import static ru.javawebinar.topjava.util.ValidationUtil.checkNotFoundWithId; - +@Service public class UserService { - private UserRepository repository; + private final UserRepository repository; + + public UserService(UserRepository repository) { + this.repository = repository; + } public User create(User user) { return repository.save(user); diff --git a/src/main/java/ru/javawebinar/topjava/web/meal/MealRestController.java b/src/main/java/ru/javawebinar/topjava/web/meal/MealRestController.java index ab4e8ea8bb8e..03bc1f78e595 100644 --- a/src/main/java/ru/javawebinar/topjava/web/meal/MealRestController.java +++ b/src/main/java/ru/javawebinar/topjava/web/meal/MealRestController.java @@ -1,7 +1,8 @@ package ru.javawebinar.topjava.web.meal; +import org.springframework.stereotype.Controller; import ru.javawebinar.topjava.service.MealService; - +@Controller public class MealRestController { private MealService service; diff --git a/src/main/java/ru/javawebinar/topjava/web/user/AbstractUserController.java b/src/main/java/ru/javawebinar/topjava/web/user/AbstractUserController.java index 16a68259ec20..e48523e0aac8 100644 --- a/src/main/java/ru/javawebinar/topjava/web/user/AbstractUserController.java +++ b/src/main/java/ru/javawebinar/topjava/web/user/AbstractUserController.java @@ -2,6 +2,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import ru.javawebinar.topjava.model.User; import ru.javawebinar.topjava.service.UserService; @@ -12,7 +13,7 @@ public abstract class AbstractUserController { protected final Logger log = LoggerFactory.getLogger(getClass()); - + @Autowired private UserService service; public List getAll() { diff --git a/src/main/java/ru/javawebinar/topjava/web/user/AdminRestController.java b/src/main/java/ru/javawebinar/topjava/web/user/AdminRestController.java index ae3374468e41..0228602c4613 100644 --- a/src/main/java/ru/javawebinar/topjava/web/user/AdminRestController.java +++ b/src/main/java/ru/javawebinar/topjava/web/user/AdminRestController.java @@ -1,9 +1,10 @@ package ru.javawebinar.topjava.web.user; +import org.springframework.stereotype.Controller; import ru.javawebinar.topjava.model.User; import java.util.List; - +@Controller public class AdminRestController extends AbstractUserController { @Override diff --git a/src/main/java/ru/javawebinar/topjava/web/user/ProfileRestController.java b/src/main/java/ru/javawebinar/topjava/web/user/ProfileRestController.java index b5062e20bc90..b161625f8155 100644 --- a/src/main/java/ru/javawebinar/topjava/web/user/ProfileRestController.java +++ b/src/main/java/ru/javawebinar/topjava/web/user/ProfileRestController.java @@ -1,9 +1,10 @@ package ru.javawebinar.topjava.web.user; +import org.springframework.stereotype.Controller; import ru.javawebinar.topjava.model.User; import static ru.javawebinar.topjava.web.SecurityUtil.authUserId; - +@Controller public class ProfileRestController extends AbstractUserController { public User get() { diff --git a/src/main/resources/spring/spring-app.xml b/src/main/resources/spring/spring-app.xml index 3a32c66999dc..c74d76f4fdf7 100644 --- a/src/main/resources/spring/spring-app.xml +++ b/src/main/resources/spring/spring-app.xml @@ -1,7 +1,16 @@ + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> - + + + + + + + + + \ No newline at end of file From 293e72de5fdb3d17768a77e39bdf38c439f3dfc2 Mon Sep 17 00:00:00 2001 From: nkashlev Date: Sat, 10 Feb 2024 18:14:44 +0300 Subject: [PATCH 15/15] 2_7_annotation_processing --- .../java/ru/javawebinar/topjava/SpringMain.java | 17 +++++------------ .../inmemory/InMemoryMealRepository.java | 3 +-- .../inmemory/InMemoryUserRepository.java | 1 + .../topjava/service/MealService.java | 3 +-- .../topjava/service/UserService.java | 1 + .../topjava/web/meal/MealRestController.java | 3 +-- .../web/user/AbstractUserController.java | 1 + .../topjava/web/user/AdminRestController.java | 1 + .../topjava/web/user/ProfileRestController.java | 1 + 9 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/main/java/ru/javawebinar/topjava/SpringMain.java b/src/main/java/ru/javawebinar/topjava/SpringMain.java index 3bf57807ea3d..c4b765681004 100644 --- a/src/main/java/ru/javawebinar/topjava/SpringMain.java +++ b/src/main/java/ru/javawebinar/topjava/SpringMain.java @@ -4,24 +4,17 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; import ru.javawebinar.topjava.model.Role; import ru.javawebinar.topjava.model.User; -import ru.javawebinar.topjava.repository.UserRepository; -import ru.javawebinar.topjava.service.UserService; +import ru.javawebinar.topjava.web.user.AdminRestController; import java.util.Arrays; public class SpringMain { public static void main(String[] args) { - try ( - ConfigurableApplicationContext appCtx = new ClassPathXmlApplicationContext("spring/spring-app.xml")) { - System.out.println("Bean definition names: " + Arrays.toString(appCtx.getBeanDefinitionNames())); - -// UserRepository userRepository = (UserRepository) appCtx.getBean("inmemoryUserRepository"); - UserRepository userRepository = appCtx.getBean(UserRepository.class); - userRepository.getAll(); - UserService userService = appCtx.getBean(UserService.class); - userService.create(new User(null, "userName", "email@mail.ru", "password", Role.ADMIN)); + try (ConfigurableApplicationContext appCtx = new ClassPathXmlApplicationContext("spring/spring-app.xml")) { + System.out.println("Bean definition names: " + Arrays.toString(appCtx.getBeanDefinitionNames())); + AdminRestController adminRestController = appCtx.getBean(AdminRestController.class); + adminRestController.create(new User(null, "userName", "email@emal.ru", "password", Role.ADMIN)); } - } } diff --git a/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryMealRepository.java b/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryMealRepository.java index 4f0f52469f65..3c7c9ff94dd2 100644 --- a/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryMealRepository.java +++ b/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryMealRepository.java @@ -1,6 +1,5 @@ package ru.javawebinar.topjava.repository.inmemory; -import org.springframework.stereotype.Repository; import ru.javawebinar.topjava.model.Meal; import ru.javawebinar.topjava.repository.MealRepository; import ru.javawebinar.topjava.util.MealsUtil; @@ -9,7 +8,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; -@Repository + public class InMemoryMealRepository implements MealRepository { private final Map repository = new ConcurrentHashMap<>(); private final AtomicInteger counter = new AtomicInteger(0); diff --git a/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryUserRepository.java b/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryUserRepository.java index 24d2510f7616..e2f8a9b8b10d 100644 --- a/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryUserRepository.java +++ b/src/main/java/ru/javawebinar/topjava/repository/inmemory/InMemoryUserRepository.java @@ -8,6 +8,7 @@ import java.util.Collections; import java.util.List; + @Repository public class InMemoryUserRepository implements UserRepository { private static final Logger log = LoggerFactory.getLogger(InMemoryUserRepository.class); diff --git a/src/main/java/ru/javawebinar/topjava/service/MealService.java b/src/main/java/ru/javawebinar/topjava/service/MealService.java index bc669b9b0228..0dc4a43c394f 100644 --- a/src/main/java/ru/javawebinar/topjava/service/MealService.java +++ b/src/main/java/ru/javawebinar/topjava/service/MealService.java @@ -1,8 +1,7 @@ package ru.javawebinar.topjava.service; -import org.springframework.stereotype.Service; import ru.javawebinar.topjava.repository.MealRepository; -@Service + public class MealService { private MealRepository repository; diff --git a/src/main/java/ru/javawebinar/topjava/service/UserService.java b/src/main/java/ru/javawebinar/topjava/service/UserService.java index d8f887b496fc..8fbe8dc0601f 100644 --- a/src/main/java/ru/javawebinar/topjava/service/UserService.java +++ b/src/main/java/ru/javawebinar/topjava/service/UserService.java @@ -8,6 +8,7 @@ import static ru.javawebinar.topjava.util.ValidationUtil.checkNotFound; import static ru.javawebinar.topjava.util.ValidationUtil.checkNotFoundWithId; + @Service public class UserService { diff --git a/src/main/java/ru/javawebinar/topjava/web/meal/MealRestController.java b/src/main/java/ru/javawebinar/topjava/web/meal/MealRestController.java index 03bc1f78e595..ab4e8ea8bb8e 100644 --- a/src/main/java/ru/javawebinar/topjava/web/meal/MealRestController.java +++ b/src/main/java/ru/javawebinar/topjava/web/meal/MealRestController.java @@ -1,8 +1,7 @@ package ru.javawebinar.topjava.web.meal; -import org.springframework.stereotype.Controller; import ru.javawebinar.topjava.service.MealService; -@Controller + public class MealRestController { private MealService service; diff --git a/src/main/java/ru/javawebinar/topjava/web/user/AbstractUserController.java b/src/main/java/ru/javawebinar/topjava/web/user/AbstractUserController.java index e48523e0aac8..0000f1c1e02f 100644 --- a/src/main/java/ru/javawebinar/topjava/web/user/AbstractUserController.java +++ b/src/main/java/ru/javawebinar/topjava/web/user/AbstractUserController.java @@ -13,6 +13,7 @@ public abstract class AbstractUserController { protected final Logger log = LoggerFactory.getLogger(getClass()); + @Autowired private UserService service; diff --git a/src/main/java/ru/javawebinar/topjava/web/user/AdminRestController.java b/src/main/java/ru/javawebinar/topjava/web/user/AdminRestController.java index 0228602c4613..b37a8ed6c8a5 100644 --- a/src/main/java/ru/javawebinar/topjava/web/user/AdminRestController.java +++ b/src/main/java/ru/javawebinar/topjava/web/user/AdminRestController.java @@ -4,6 +4,7 @@ import ru.javawebinar.topjava.model.User; import java.util.List; + @Controller public class AdminRestController extends AbstractUserController { diff --git a/src/main/java/ru/javawebinar/topjava/web/user/ProfileRestController.java b/src/main/java/ru/javawebinar/topjava/web/user/ProfileRestController.java index b161625f8155..7d3702c31c46 100644 --- a/src/main/java/ru/javawebinar/topjava/web/user/ProfileRestController.java +++ b/src/main/java/ru/javawebinar/topjava/web/user/ProfileRestController.java @@ -4,6 +4,7 @@ import ru.javawebinar.topjava.model.User; import static ru.javawebinar.topjava.web.SecurityUtil.authUserId; + @Controller public class ProfileRestController extends AbstractUserController {