diff --git a/2021-03/spring-15-mvc/.gitignore b/2021-03/spring-15-mvc/.gitignore
deleted file mode 100644
index 4ea52072..00000000
--- a/2021-03/spring-15-mvc/.gitignore
+++ /dev/null
@@ -1,24 +0,0 @@
-target/
-
-### STS ###
-.apt_generated
-.classpath
-.factorypath
-.project
-.settings
-.springBeans
-.sts4-cache
-
-### IntelliJ IDEA ###
-.idea
-*.iws
-*.iml
-*.ipr
-
-### NetBeans ###
-/nbproject/private/
-/build/
-/nbbuild/
-/dist/
-/nbdist/
-/.nb-gradle/
diff --git a/2021-03/spring-15-mvc/requests.http b/2021-03/spring-15-mvc/requests.http
deleted file mode 100644
index e892d644..00000000
--- a/2021-03/spring-15-mvc/requests.http
+++ /dev/null
@@ -1,11 +0,0 @@
-POST http://localhost:8080/person
-Content-Type: application/json
-
-{
- "id": "1",
- "name": "Gogol'"
-}
-
-###
-GET http://localhost:8080/person
-
diff --git a/2021-03/spring-15-mvc/spring-mvc-solution-4/pom.xml b/2021-03/spring-15-mvc/spring-mvc-demo/pom.xml
similarity index 96%
rename from 2021-03/spring-15-mvc/spring-mvc-solution-4/pom.xml
rename to 2021-03/spring-15-mvc/spring-mvc-demo/pom.xml
index 3aa7eeb1..0eee1791 100644
--- a/2021-03/spring-15-mvc/spring-mvc-solution-4/pom.xml
+++ b/2021-03/spring-15-mvc/spring-mvc-demo/pom.xml
@@ -5,7 +5,7 @@
4.0.0
ru.otus
- spring-mvc-solution-4
+ spring-mvc-demo
1.0
diff --git a/2021-03/spring-15-mvc/spring-mvc-solution-4/src/main/java/ru/otus/spring/Main.java b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/Main.java
similarity index 100%
rename from 2021-03/spring-15-mvc/spring-mvc-solution-4/src/main/java/ru/otus/spring/Main.java
rename to 2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/Main.java
diff --git a/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/config/WebConfig.java b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/config/WebConfig.java
new file mode 100644
index 00000000..0513c3d5
--- /dev/null
+++ b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/config/WebConfig.java
@@ -0,0 +1,22 @@
+package ru.otus.spring.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import ru.otus.spring.rest.SystemInfoMethodArgumentResolver;
+import ru.otus.spring.service.SystemInfoService;
+
+import java.util.List;
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+ @Autowired
+ private SystemInfoService systemInfoService;
+
+ @Override
+ public void addArgumentResolvers(List resolvers) {
+ resolvers.add(new SystemInfoMethodArgumentResolver(systemInfoService));
+ }
+}
diff --git a/2021-03/spring-15-mvc/spring-mvc-solution-4/src/main/java/ru/otus/spring/domain/Person.java b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/domain/Person.java
similarity index 100%
rename from 2021-03/spring-15-mvc/spring-mvc-solution-4/src/main/java/ru/otus/spring/domain/Person.java
rename to 2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/domain/Person.java
diff --git a/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/domain/SystemInfo.java b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/domain/SystemInfo.java
new file mode 100644
index 00000000..40deaaee
--- /dev/null
+++ b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/domain/SystemInfo.java
@@ -0,0 +1,19 @@
+package ru.otus.spring.domain;
+
+public class SystemInfo {
+ private final String osName;
+ private final String timeZone;
+ private final String osArch;
+ private final int processorsCount;
+
+ public SystemInfo(String osName, String timeZone, String osArch, int processorsCount) {
+ this.osName = osName;
+ this.timeZone = timeZone;
+ this.osArch = osArch;
+ this.processorsCount = processorsCount;
+ }
+
+ public String getOsName() {
+ return osName;
+ }
+}
diff --git a/2021-03/spring-15-mvc/spring-mvc-solution-4/src/main/java/ru/otus/spring/repostory/PersonRepository.java b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/repostory/PersonRepository.java
similarity index 100%
rename from 2021-03/spring-15-mvc/spring-mvc-solution-4/src/main/java/ru/otus/spring/repostory/PersonRepository.java
rename to 2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/repostory/PersonRepository.java
diff --git a/2021-03/spring-15-mvc/spring-mvc-solution-4/src/main/java/ru/otus/spring/rest/ErrorHandler.java b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/rest/ErrorHandler.java
similarity index 100%
rename from 2021-03/spring-15-mvc/spring-mvc-solution-4/src/main/java/ru/otus/spring/rest/ErrorHandler.java
rename to 2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/rest/ErrorHandler.java
diff --git a/2021-03/spring-15-mvc/spring-mvc-solution-4/src/main/java/ru/otus/spring/rest/NotFoundException.java b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/rest/NotFoundException.java
similarity index 100%
rename from 2021-03/spring-15-mvc/spring-mvc-solution-4/src/main/java/ru/otus/spring/rest/NotFoundException.java
rename to 2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/rest/NotFoundException.java
diff --git a/2021-03/spring-15-mvc/spring-mvc-solution-4/src/main/java/ru/otus/spring/rest/PersonController.java b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/rest/PersonController.java
similarity index 100%
rename from 2021-03/spring-15-mvc/spring-mvc-solution-4/src/main/java/ru/otus/spring/rest/PersonController.java
rename to 2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/rest/PersonController.java
diff --git a/2021-03/spring-15-mvc/spring-mvc-solution-4/src/main/java/ru/otus/spring/rest/PersonDto.java b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/rest/PersonDto.java
similarity index 100%
rename from 2021-03/spring-15-mvc/spring-mvc-solution-4/src/main/java/ru/otus/spring/rest/PersonDto.java
rename to 2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/rest/PersonDto.java
diff --git a/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/rest/SystemInfoController.java b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/rest/SystemInfoController.java
new file mode 100644
index 00000000..88ccc448
--- /dev/null
+++ b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/rest/SystemInfoController.java
@@ -0,0 +1,14 @@
+package ru.otus.spring.rest;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+import ru.otus.spring.domain.SystemInfo;
+
+@RestController
+public class SystemInfoController {
+
+ @GetMapping("/server/system/info")
+ public SystemInfo getServerSystemInfo(SystemInfo systemInfo) {
+ return systemInfo;
+ }
+}
diff --git a/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/rest/SystemInfoMethodArgumentResolver.java b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/rest/SystemInfoMethodArgumentResolver.java
new file mode 100644
index 00000000..601ab48c
--- /dev/null
+++ b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/rest/SystemInfoMethodArgumentResolver.java
@@ -0,0 +1,31 @@
+package ru.otus.spring.rest;
+
+import org.springframework.core.MethodParameter;
+import org.springframework.web.bind.support.WebDataBinderFactory;
+import org.springframework.web.context.request.NativeWebRequest;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.method.support.ModelAndViewContainer;
+import ru.otus.spring.domain.SystemInfo;
+import ru.otus.spring.service.SystemInfoService;
+
+public class SystemInfoMethodArgumentResolver implements HandlerMethodArgumentResolver {
+
+ private final SystemInfoService systemInfoService;
+
+ public SystemInfoMethodArgumentResolver(SystemInfoService systemInfoService) {
+ this.systemInfoService = systemInfoService;
+ }
+
+ @Override
+ public boolean supportsParameter(MethodParameter parameter) {
+ return parameter.getParameterType().equals(SystemInfo.class);
+ }
+
+ @Override
+ public Object resolveArgument(MethodParameter parameter,
+ ModelAndViewContainer mavContainer,
+ NativeWebRequest webRequest,
+ WebDataBinderFactory binderFactory) throws Exception {
+ return systemInfoService.getSystemInfo();
+ }
+}
diff --git a/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/service/SystemInfoService.java b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/service/SystemInfoService.java
new file mode 100644
index 00000000..3914948f
--- /dev/null
+++ b/2021-03/spring-15-mvc/spring-mvc-demo/src/main/java/ru/otus/spring/service/SystemInfoService.java
@@ -0,0 +1,17 @@
+package ru.otus.spring.service;
+
+import org.springframework.stereotype.Service;
+import ru.otus.spring.domain.SystemInfo;
+
+@Service
+public class SystemInfoService {
+//
+ public SystemInfo getSystemInfo(){
+ String osName = System.getProperty("os.name");
+ String timeZone = System.getProperty("user.timezone");
+ String osArch = System.getProperty("os.arch");
+ int processorsCount = Runtime.getRuntime().availableProcessors();;
+ return new SystemInfo(osName, timeZone, osArch, processorsCount);
+ //HandlerMethodArgumentResolver
+ }
+}
diff --git a/2021-03/spring-15-mvc/spring-mvc-solution-4/src/test/java/ru/otus/spring/rest/PersonControllerTest.java b/2021-03/spring-15-mvc/spring-mvc-demo/src/test/java/ru/otus/spring/rest/PersonControllerTest.java
similarity index 100%
rename from 2021-03/spring-15-mvc/spring-mvc-solution-4/src/test/java/ru/otus/spring/rest/PersonControllerTest.java
rename to 2021-03/spring-15-mvc/spring-mvc-demo/src/test/java/ru/otus/spring/rest/PersonControllerTest.java
diff --git a/2021-03/spring-15-mvc/spring-mvc-demo/src/test/java/ru/otus/spring/rest/SystemInfoControllerTest.java b/2021-03/spring-15-mvc/spring-mvc-demo/src/test/java/ru/otus/spring/rest/SystemInfoControllerTest.java
new file mode 100644
index 00000000..33f81220
--- /dev/null
+++ b/2021-03/spring-15-mvc/spring-mvc-demo/src/test/java/ru/otus/spring/rest/SystemInfoControllerTest.java
@@ -0,0 +1,34 @@
+package ru.otus.spring.rest;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.web.servlet.MockMvc;
+import ru.otus.spring.domain.SystemInfo;
+import ru.otus.spring.service.SystemInfoService;
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+
+@WebMvcTest(SystemInfoController.class)
+@Import(SystemInfoService.class)
+class SystemInfoControllerTest {
+
+ @Autowired
+ private MockMvc mvc;
+
+ @Autowired
+ private ObjectMapper mapper;
+
+ @Autowired
+ private SystemInfoService systemInfoService;
+
+ @Test
+ void shouldReturnCorrectServerSystemInfo() throws Exception {
+ SystemInfo expectedSystemInfo = systemInfoService.getSystemInfo();
+ mvc.perform(get("/server/system/info"))
+ .andExpect(content().json(mapper.writeValueAsString(expectedSystemInfo)));
+ }
+}
\ No newline at end of file
diff --git a/2021-03/spring-15-mvc/spring-mvc-exercise/.gitignore b/2021-03/spring-15-mvc/spring-mvc-exercise/.gitignore
deleted file mode 100644
index 4ea52072..00000000
--- a/2021-03/spring-15-mvc/spring-mvc-exercise/.gitignore
+++ /dev/null
@@ -1,24 +0,0 @@
-target/
-
-### STS ###
-.apt_generated
-.classpath
-.factorypath
-.project
-.settings
-.springBeans
-.sts4-cache
-
-### IntelliJ IDEA ###
-.idea
-*.iws
-*.iml
-*.ipr
-
-### NetBeans ###
-/nbproject/private/
-/build/
-/nbbuild/
-/dist/
-/nbdist/
-/.nb-gradle/
diff --git a/2021-03/spring-15-mvc/spring-mvc-solution-1/.gitignore b/2021-03/spring-15-mvc/spring-mvc-solution-1/.gitignore
deleted file mode 100644
index 4ea52072..00000000
--- a/2021-03/spring-15-mvc/spring-mvc-solution-1/.gitignore
+++ /dev/null
@@ -1,24 +0,0 @@
-target/
-
-### STS ###
-.apt_generated
-.classpath
-.factorypath
-.project
-.settings
-.springBeans
-.sts4-cache
-
-### IntelliJ IDEA ###
-.idea
-*.iws
-*.iml
-*.ipr
-
-### NetBeans ###
-/nbproject/private/
-/build/
-/nbbuild/
-/dist/
-/nbdist/
-/.nb-gradle/
diff --git a/2021-03/spring-15-mvc/spring-mvc-solution-2/.gitignore b/2021-03/spring-15-mvc/spring-mvc-solution-2/.gitignore
deleted file mode 100644
index 4ea52072..00000000
--- a/2021-03/spring-15-mvc/spring-mvc-solution-2/.gitignore
+++ /dev/null
@@ -1,24 +0,0 @@
-target/
-
-### STS ###
-.apt_generated
-.classpath
-.factorypath
-.project
-.settings
-.springBeans
-.sts4-cache
-
-### IntelliJ IDEA ###
-.idea
-*.iws
-*.iml
-*.ipr
-
-### NetBeans ###
-/nbproject/private/
-/build/
-/nbbuild/
-/dist/
-/nbdist/
-/.nb-gradle/
diff --git a/2021-03/spring-15-mvc/spring-mvc-solution-3/.gitignore b/2021-03/spring-15-mvc/spring-mvc-solution-3/.gitignore
deleted file mode 100644
index 4ea52072..00000000
--- a/2021-03/spring-15-mvc/spring-mvc-solution-3/.gitignore
+++ /dev/null
@@ -1,24 +0,0 @@
-target/
-
-### STS ###
-.apt_generated
-.classpath
-.factorypath
-.project
-.settings
-.springBeans
-.sts4-cache
-
-### IntelliJ IDEA ###
-.idea
-*.iws
-*.iml
-*.ipr
-
-### NetBeans ###
-/nbproject/private/
-/build/
-/nbbuild/
-/dist/
-/nbdist/
-/.nb-gradle/
diff --git a/2021-03/spring-15-mvc/spring-mvc-solution-4/.gitignore b/2021-03/spring-15-mvc/spring-mvc-solution-4/.gitignore
deleted file mode 100644
index 4ea52072..00000000
--- a/2021-03/spring-15-mvc/spring-mvc-solution-4/.gitignore
+++ /dev/null
@@ -1,24 +0,0 @@
-target/
-
-### STS ###
-.apt_generated
-.classpath
-.factorypath
-.project
-.settings
-.springBeans
-.sts4-cache
-
-### IntelliJ IDEA ###
-.idea
-*.iws
-*.iml
-*.ipr
-
-### NetBeans ###
-/nbproject/private/
-/build/
-/nbbuild/
-/dist/
-/nbdist/
-/.nb-gradle/