diff --git a/0-0-intro/0-0-1-welcome-to-java-web-exercises/README.MD b/0-0-intro/0-0-1-welcome-to-java-web-exercises/README.MD deleted file mode 100644 index 4aecf01..0000000 --- a/0-0-intro/0-0-1-welcome-to-java-web-exercises/README.MD +++ /dev/null @@ -1,17 +0,0 @@ -# Welcome to Java Web Exercises - -This is a welcome test project to check if everything works okay on your computer - -### You should have installed on your local machine ❗️ -* [JDK 17+](hhttps://jdk.java.net/17/) -* [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) - -### How to start ❓ - -* Just **clone the repository** to your computer -* Open project in your IDE and **configure JDK 17** for the project -* Open terminal and **run a command** `./mvnw clean package` (UNIX) or `mvnw.cmd clean package` (Windows) -* Open class `WelcomeToJavaWebCourseApp` and **run** `main()` -* [Click here](http://localhost:8080/welcome) 🔗 - -### You'll see if it works 😉 diff --git a/0-0-intro/0-0-1-welcome-to-java-web-exercises/pom.xml b/0-0-intro/0-0-1-welcome-to-java-web-exercises/pom.xml deleted file mode 100644 index 7f9b236..0000000 --- a/0-0-intro/0-0-1-welcome-to-java-web-exercises/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - 0-0-intro - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 0-0-1-welcome-to-java-web-exercises - - - UTF-8 - UTF-8 - - - - - org.springframework.boot - spring-boot-starter-thymeleaf - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - 2.7.3 - - - - - - - - org.springframework.boot - spring-boot-dependencies - 2.4.0 - pom - import - - - - - - \ No newline at end of file diff --git a/0-0-intro/0-0-1-welcome-to-java-web-exercises/src/main/java/com/bobocode/intro/WelcomeToJavaWebCourseApp.java b/0-0-intro/0-0-1-welcome-to-java-web-exercises/src/main/java/com/bobocode/intro/WelcomeToJavaWebCourseApp.java deleted file mode 100644 index b4787c1..0000000 --- a/0-0-intro/0-0-1-welcome-to-java-web-exercises/src/main/java/com/bobocode/intro/WelcomeToJavaWebCourseApp.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.bobocode.intro; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; - -@SpringBootApplication -@Controller -public class WelcomeToJavaWebCourseApp { - - public static void main(String[] args) { - SpringApplication.run(WelcomeToJavaWebCourseApp.class, args); - } - - @GetMapping({"", "/welcome"}) - public String welcome(@RequestParam(value = "name", required = false) String name, Model model) { - model.addAttribute("name", name); - return "welcome"; - } -} diff --git a/0-0-intro/0-0-1-welcome-to-java-web-exercises/src/main/resources/static/logo.png b/0-0-intro/0-0-1-welcome-to-java-web-exercises/src/main/resources/static/logo.png deleted file mode 100644 index 371a4a7..0000000 Binary files a/0-0-intro/0-0-1-welcome-to-java-web-exercises/src/main/resources/static/logo.png and /dev/null differ diff --git a/0-0-intro/0-0-1-welcome-to-java-web-exercises/src/main/resources/templates/welcome.html b/0-0-intro/0-0-1-welcome-to-java-web-exercises/src/main/resources/templates/welcome.html deleted file mode 100644 index ab5410c..0000000 --- a/0-0-intro/0-0-1-welcome-to-java-web-exercises/src/main/resources/templates/welcome.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Welcome to Bobocode! - - -

-

Welcome to Java Web Exercises

-
- -
-
-

- * change the URL to http://localhost:8080/welcome?name=YourName -

-
- - \ No newline at end of file diff --git a/0-0-intro/pom.xml b/0-0-intro/pom.xml deleted file mode 100644 index 19c2659..0000000 --- a/0-0-intro/pom.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - java-web-exercises - com.bobocode - 1.0-SNAPSHOT - - 4.0.0 - - 0-0-intro - pom - - 0-0-1-welcome-to-java-web-exercises - - - \ No newline at end of file diff --git a/1-0-networking-and-http/1-0-0-hello-network-socket/src/main/java/com/bobocode/net/client/ClientUtil.java b/1-0-networking-and-http/1-0-0-hello-network-socket/src/main/java/com/bobocode/net/client/ClientUtil.java index e2cdac5..4b26b87 100644 --- a/1-0-networking-and-http/1-0-0-hello-network-socket/src/main/java/com/bobocode/net/client/ClientUtil.java +++ b/1-0-networking-and-http/1-0-0-hello-network-socket/src/main/java/com/bobocode/net/client/ClientUtil.java @@ -24,7 +24,7 @@ private ClientUtil() { */ @SneakyThrows public static Socket openSocket(String host, int port) { - throw new ExerciseNotCompletedException(); // todo: implement according to javadoc and verify by ClientUtilTest + return new Socket(host, port); } /** @@ -62,6 +62,10 @@ public static String readMessage(BufferedReader reader) { */ @SneakyThrows public static void writeToSocket(String message, Socket socket) { - throw new ExerciseNotCompletedException(); // todo: implement according to javadoc and verify by ClientUtilTest + OutputStream outputStream = socket.getOutputStream(); + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream)); + + writer.write(message); + writer.flush(); } } diff --git a/1-0-networking-and-http/1-0-0-hello-network-socket/src/main/java/com/bobocode/net/server/ServerUtil.java b/1-0-networking-and-http/1-0-0-hello-network-socket/src/main/java/com/bobocode/net/server/ServerUtil.java index 3778579..2e501d3 100644 --- a/1-0-networking-and-http/1-0-0-hello-network-socket/src/main/java/com/bobocode/net/server/ServerUtil.java +++ b/1-0-networking-and-http/1-0-0-hello-network-socket/src/main/java/com/bobocode/net/server/ServerUtil.java @@ -41,7 +41,7 @@ public static String getLocalHost() { */ @SneakyThrows public static ServerSocket createServerSocket(int port) { - throw new ExerciseNotCompletedException(); // todo: implement according to javadoc and verify by ServerUtilTest + return new ServerSocket(port); } /** @@ -52,7 +52,7 @@ public static ServerSocket createServerSocket(int port) { */ @SneakyThrows public static Socket acceptClientSocket(ServerSocket serverSocket) { - throw new ExerciseNotCompletedException(); // todo: implement according to javadoc and verify by ServerUtilTest + return serverSocket.accept(); } /** @@ -66,7 +66,9 @@ public static Socket acceptClientSocket(ServerSocket serverSocket) { */ @SneakyThrows public static String readMessageFromSocket(Socket socket) { - throw new ExerciseNotCompletedException(); // todo: implement according to javadoc and verify by ServerUtilTest + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); + + return bufferedReader.readLine(); } /** diff --git a/2-0-servlet-api/2-0-1-hello-servlet-api/src/main/java/com/bobocode/servlet/DateServlet.java b/2-0-servlet-api/2-0-1-hello-servlet-api/src/main/java/com/bobocode/servlet/DateServlet.java new file mode 100644 index 0000000..13751d7 --- /dev/null +++ b/2-0-servlet-api/2-0-1-hello-servlet-api/src/main/java/com/bobocode/servlet/DateServlet.java @@ -0,0 +1,21 @@ +package com.bobocode.servlet; + +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; +import java.io.PrintWriter; +import java.time.LocalDate; + +@WebServlet("/date") +public class DateServlet extends HttpServlet { + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + PrintWriter out = resp.getWriter(); + out.println(LocalDate.now()); + } +} diff --git a/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/config/ApplicationConfig.java b/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/config/ApplicationConfig.java index f7ebf38..d7c83f7 100644 --- a/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/config/ApplicationConfig.java +++ b/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/config/ApplicationConfig.java @@ -1,6 +1,11 @@ package com.bobocode.config; import com.bobocode.TestDataGenerator; +import com.bobocode.dao.FakeAccountDao; +import com.bobocode.service.AccountService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; /** * This class specifies application context configuration. It tells Spring to scan "dao" and "service" packages in order @@ -10,7 +15,12 @@ * It also explicitly configures a bean of {@link TestDataGenerator} called "dataGenerator". This beans will be injected * into {@link com.bobocode.dao.FakeAccountDao} in order to generate some fake accounts. */ +@Configuration +@ComponentScan(basePackages = {"com.bobocode.dao", "com.bobocode.service"}) public class ApplicationConfig { - // todo: configure application context according to javadoc by following tests in ApplicationConfigTest - // todo: verify final implementation by running ApplicationContextTest + + @Bean + public TestDataGenerator dataGenerator() { + return new TestDataGenerator(); + } } diff --git a/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/dao/FakeAccountDao.java b/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/dao/FakeAccountDao.java index bae7264..988a90b 100644 --- a/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/dao/FakeAccountDao.java +++ b/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/dao/FakeAccountDao.java @@ -2,6 +2,8 @@ import com.bobocode.TestDataGenerator; import com.bobocode.model.Account; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; import java.util.List; import java.util.stream.Stream; @@ -16,9 +18,11 @@ * Its bean is called "accountDao". And it uses constructor with explicit autowired annotation in order to inject * {@link TestDataGenerator} instance. */ +@Component("accountDao") public class FakeAccountDao implements AccountDao { private List accounts; + @Autowired public FakeAccountDao(TestDataGenerator testDataGenerator) { this.accounts = Stream.generate(testDataGenerator::generateAccount) .limit(20) diff --git a/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/service/AccountService.java b/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/service/AccountService.java index a46dfd2..d6d69b8 100644 --- a/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/service/AccountService.java +++ b/3-0-spring-framework/3-0-0-hello-spring-framework/src/main/java/com/bobocode/service/AccountService.java @@ -2,6 +2,7 @@ import com.bobocode.dao.AccountDao; import com.bobocode.model.Account; +import org.springframework.stereotype.Service; import static java.util.Comparator.comparing; @@ -12,6 +13,7 @@ * Since it's a service that should be added to the application context, it is marked as Spring service. It order to get * {@link AccountDao} instances, it uses implicit constructor-based injection. */ +@Service public class AccountService { private final AccountDao accountDao; diff --git a/3-0-spring-framework/3-0-1-hello-spring-mvc/src/main/java/com/bobocode/mvc/api/NoteRestController.java b/3-0-spring-framework/3-0-1-hello-spring-mvc/src/main/java/com/bobocode/mvc/api/NoteRestController.java index 95d9ed6..f5baf00 100644 --- a/3-0-spring-framework/3-0-1-hello-spring-mvc/src/main/java/com/bobocode/mvc/api/NoteRestController.java +++ b/3-0-spring-framework/3-0-1-hello-spring-mvc/src/main/java/com/bobocode/mvc/api/NoteRestController.java @@ -1,7 +1,11 @@ package com.bobocode.mvc.api; import com.bobocode.mvc.data.Notes; +import com.bobocode.mvc.model.Note; import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; /** * This controller provides a very simple REST API for Notes. It implements two endpoints that allow you to add @@ -18,9 +22,21 @@ * Spring MVC was used to build the whole application including front-end. So the controllers were connected to the views * via models, like in {@link com.bobocode.mvc.controller.NoteController} */ +@RestController +@RequestMapping("/api/notes") @RequiredArgsConstructor public class NoteRestController { private final Notes notes; - // TODO: implement controller methods according to the javadoc verify your impl using NoteRestControllerTest + @GetMapping + public List getNotes() { + return notes.getAll(); + } + + @PostMapping + public void addNote( + @RequestBody Note note + ) { + notes.add(note); + } } diff --git a/3-0-spring-framework/3-0-1-hello-spring-mvc/src/main/java/com/bobocode/mvc/controller/NoteController.java b/3-0-spring-framework/3-0-1-hello-spring-mvc/src/main/java/com/bobocode/mvc/controller/NoteController.java index 3f9d528..4b35f16 100644 --- a/3-0-spring-framework/3-0-1-hello-spring-mvc/src/main/java/com/bobocode/mvc/controller/NoteController.java +++ b/3-0-spring-framework/3-0-1-hello-spring-mvc/src/main/java/com/bobocode/mvc/controller/NoteController.java @@ -1,7 +1,15 @@ package com.bobocode.mvc.controller; import com.bobocode.mvc.data.Notes; +import com.bobocode.mvc.model.Note; import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import java.util.List; /** * {@link NoteController} is a typical controller that powers Spring MVC Notes application. This application provides @@ -26,10 +34,24 @@ * back-end applications. The back-end app, will only need to provide data and don't care about view. In that case * the same controller will look like {@link com.bobocode.mvc.api.NoteRestController} */ +@Controller @RequiredArgsConstructor +@RequestMapping("/notes") public class NoteController { private final Notes notes; - // TODO: implement controller methods according to the javadoc and verify your impl using NoteControllerTest + @GetMapping + public String notesPage(Model model) { + List noteList = notes.getAll(); + model.addAttribute("noteList", noteList); + + return "notes"; + } + + @PostMapping + public String addNote(Note note) { + notes.add(note); + return "redirect:/notes"; + } } diff --git a/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/RootConfig.java b/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/RootConfig.java index 6536634..f32eeb2 100644 --- a/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/RootConfig.java +++ b/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/RootConfig.java @@ -1,8 +1,8 @@ package com.bobocode.config; import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.stereotype.Controller; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @@ -11,9 +11,12 @@ * (containing middle-tire services, datasource, etc.). * The configuration must exclude the web layer of the application. *

- * todo: mark this class as config - * todo: enable component scanning for all packages in "com.bobocode" - * todo: ignore all web related config and beans (ignore @{@link Controller}, ignore {@link EnableWebMvc}) using exclude filter */ +@Configuration +@ComponentScan(basePackages = "com.bobocode", + excludeFilters = { + @ComponentScan.Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class), + @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class), + }) public class RootConfig { } diff --git a/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/WebAppInitializer.java b/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/WebAppInitializer.java index ee23400..e4c4b8a 100644 --- a/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/WebAppInitializer.java +++ b/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/WebAppInitializer.java @@ -1,6 +1,5 @@ package com.bobocode.config; -import com.bobocode.util.ExerciseNotCompletedException; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; /** @@ -9,16 +8,16 @@ public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class[] getRootConfigClasses() { - throw new ExerciseNotCompletedException(); //todo: use {@link RootConfig} as root application config class + return new Class[]{RootConfig.class}; } @Override protected Class[] getServletConfigClasses() { - throw new ExerciseNotCompletedException(); //todo: use {@link WebConfig} as ServletConfig class + return new Class[]{WebConfig.class}; } @Override protected String[] getServletMappings() { - throw new ExerciseNotCompletedException(); //todo: provide default servlet mapping ("/") + return new String[]{"/"}; } } diff --git a/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/WebConfig.java b/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/WebConfig.java index 66d3a84..dff4f92 100644 --- a/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/WebConfig.java +++ b/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/config/WebConfig.java @@ -9,10 +9,9 @@ * each DispatcherServlet has its own WebApplicationContext, which inherits all the beans already defined * in the root ApplicationContext. *

- * todo: mark this class as Spring config class - * todo: enable web mvc using annotation - * todo: enable component scanning for package "web" */ - +@Configuration +@EnableWebMvc +@ComponentScan(basePackages = "com.bobocode.web") public class WebConfig { } diff --git a/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/web/controller/WelcomeController.java b/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/web/controller/WelcomeController.java index 77392cc..9da6e2b 100644 --- a/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/web/controller/WelcomeController.java +++ b/3-0-spring-framework/3-1-1-dispatcher-servlet-initializer/src/main/java/com/bobocode/web/controller/WelcomeController.java @@ -1,16 +1,20 @@ package com.bobocode.web.controller; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ResponseBody; + /** * Welcome controller that consists of one method that handles get request to "/welcome" and respond with a message. *

- * todo: mark this class as Spring controller - * todo: configure HTTP GET mapping "/welcome" for method {@link WelcomeController#welcome()} - * todo: tell Spring that {@link WelcomeController#welcome()} method provides response body without view */ - +@Controller public class WelcomeController { + @GetMapping("/welcome") + @ResponseBody public String welcome() { - return "Welcome to Spring MVC!"; + + return "welcome"; } } diff --git a/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/config/RootConfig.java b/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/config/RootConfig.java index c5d1a6d..923ba57 100644 --- a/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/config/RootConfig.java +++ b/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/config/RootConfig.java @@ -1,14 +1,20 @@ package com.bobocode.config; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.stereotype.Controller; import org.springframework.web.servlet.config.annotation.EnableWebMvc; /** * This class provides application root (non-web) configuration. *

- * todo: 1. Mark this class as config - * todo: 2. Enable component scanning for all packages in "com.bobocode" using annotation property "basePackages" - * todo: 3. Exclude web related config and beans (ignore @{@link Controller}, ignore {@link EnableWebMvc}) */ +@Configuration +@ComponentScan(basePackages = "com.bobocode", + excludeFilters = { + @ComponentScan.Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class), + @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class), + }) public class RootConfig { } diff --git a/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/config/WebConfig.java b/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/config/WebConfig.java index 1197302..546ce63 100644 --- a/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/config/WebConfig.java +++ b/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/config/WebConfig.java @@ -1,11 +1,15 @@ package com.bobocode.config; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + /** * This class provides web (servlet) related configuration. *

- * todo: 1. Mark this class as Spring config class - * todo: 2. Enable web mvc using annotation - * todo: 3. Enable component scanning for package "web" using annotation value */ +@Configuration +@EnableWebMvc +@ComponentScan(basePackages = "com.bobocode.web") public class WebConfig { } diff --git a/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/dao/impl/InMemoryAccountDao.java b/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/dao/impl/InMemoryAccountDao.java index 5620d5b..f531ce7 100644 --- a/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/dao/impl/InMemoryAccountDao.java +++ b/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/dao/impl/InMemoryAccountDao.java @@ -3,6 +3,7 @@ import com.bobocode.dao.AccountDao; import com.bobocode.exception.EntityNotFountException; import com.bobocode.model.Account; +import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.HashMap; @@ -12,8 +13,8 @@ /** * {@link AccountDao} implementation that is based on {@link java.util.HashMap}. *

- * todo: 1. Configure a component with name "accountDao" */ +@Component("accountDao") public class InMemoryAccountDao implements AccountDao { private Map accountMap = new HashMap<>(); private long idSequence = 1L; diff --git a/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/web/controller/AccountRestController.java b/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/web/controller/AccountRestController.java index 84fb818..ab0f01c 100644 --- a/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/web/controller/AccountRestController.java +++ b/3-0-spring-framework/3-2-1-account-rest-api/src/main/java/com/bobocode/web/controller/AccountRestController.java @@ -1,21 +1,63 @@ package com.bobocode.web.controller; import com.bobocode.dao.AccountDao; +import com.bobocode.model.Account; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; /** *

- * todo: 1. Configure rest controller that handles requests with url "/accounts" - * todo: 2. Inject {@link AccountDao} implementation - * todo: 3. Implement method that handles GET request and returns a list of accounts - * todo: 4. Implement method that handles GET request with id as path variable and returns account by id - * todo: 5. Implement method that handles POST request, receives account as request body, saves account and returns it - * todo: Configure HTTP response status code 201 - CREATED - * todo: 6. Implement method that handles PUT request with id as path variable and receives account as request body. - * todo: It check if account id and path variable are the same and throws {@link IllegalStateException} otherwise. - * todo: Then it saves received account. Configure HTTP response status code 204 - NO CONTENT - * todo: 7. Implement method that handles DELETE request with id as path variable removes an account by id - * todo: Configure HTTP response status code 204 - NO CONTENT */ +@RestController +@RequestMapping("/accounts") +@RequiredArgsConstructor public class AccountRestController { + private final AccountDao accountDao; + + @GetMapping + public List getAccounts() { + return accountDao.findAll(); + } + + @GetMapping("/{id}") + public Account getAccount( + @PathVariable long id + ) { + return accountDao.findById(id); + } + + @PostMapping + public ResponseEntity saveUser( + @RequestBody Account account + ) { + return ResponseEntity.status(HttpStatus.CREATED).body(accountDao.save(account)); + } + + @PutMapping("/{id}") + public ResponseEntity updateUser( + @PathVariable long id, + @RequestBody Account account + ) { + if (account.getId() != id) { + throw new IllegalStateException(); + } + accountDao.save(account); + + return ResponseEntity.noContent().build(); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteUser( + @PathVariable long id + ) { + Account account = accountDao.findById(id); + accountDao.remove(account); + + return ResponseEntity.noContent().build(); + } } diff --git a/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/StringTrimmingConfiguration.java b/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/StringTrimmingConfiguration.java new file mode 100644 index 0000000..87495de --- /dev/null +++ b/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/StringTrimmingConfiguration.java @@ -0,0 +1,11 @@ +package com.bobocode; + +import org.springframework.context.annotation.Bean; + +public class StringTrimmingConfiguration { + + @Bean + public TrimmedAnnotationBeanPostProcessor trimmedAnnotationBeanPostProcessor() { + return new TrimmedAnnotationBeanPostProcessor(); + } +} diff --git a/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/TrimmedAnnotationBeanPostProcessor.java b/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/TrimmedAnnotationBeanPostProcessor.java index ee1d441..d3d52df 100644 --- a/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/TrimmedAnnotationBeanPostProcessor.java +++ b/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/TrimmedAnnotationBeanPostProcessor.java @@ -1,10 +1,16 @@ package com.bobocode; +import com.bobocode.annotation.EnableStringTrimming; import com.bobocode.annotation.Trimmed; import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.cglib.proxy.Enhancer; +import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; + /** * This is processor class implements {@link BeanPostProcessor}, looks for a beans where method parameters are marked with * {@link Trimmed} annotation, creates proxy of them, overrides methods and trims all {@link String} arguments marked with @@ -16,6 +22,59 @@ * {@link StringTrimmingConfiguration} class which can be imported to a {@link Configuration} class by annotation * {@link EnableStringTrimming} */ -public class TrimmedAnnotationBeanPostProcessor { -//todo: Implement TrimmedAnnotationBeanPostProcessor according to javadoc +public class TrimmedAnnotationBeanPostProcessor implements BeanPostProcessor { + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) { + Class beanClass = bean.getClass(); + if (!hasTrimmedStringParameter(beanClass)) { + return bean; + } + + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(beanClass); + enhancer.setCallback((MethodInterceptor) (proxy, method, args, methodProxy) -> { + Object[] processedArgs = trimAnnotatedStringArguments(beanClass, method, args); + return method.invoke(bean, processedArgs); + }); + return enhancer.create(); + } + + private boolean hasTrimmedStringParameter(Class beanClass) { + for (Method method : beanClass.getMethods()) { + Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + Class[] parameterTypes = method.getParameterTypes(); + for (int i = 0; i < parameterTypes.length; i++) { + if (parameterTypes[i].equals(String.class) && hasTrimmedAnnotation(parameterAnnotations[i])) { + return true; + } + } + } + return false; + } + + private Object[] trimAnnotatedStringArguments(Class beanClass, Method proxyMethod, Object[] args) throws NoSuchMethodException { + Method beanMethod = beanClass.getMethod(proxyMethod.getName(), proxyMethod.getParameterTypes()); + Annotation[][] parameterAnnotations = beanMethod.getParameterAnnotations(); + Class[] parameterTypes = beanMethod.getParameterTypes(); + + Object[] processedArgs = args.clone(); + for (int i = 0; i < parameterTypes.length; i++) { + if (parameterTypes[i].equals(String.class) + && processedArgs[i] != null + && hasTrimmedAnnotation(parameterAnnotations[i])) { + processedArgs[i] = ((String) processedArgs[i]).trim(); + } + } + return processedArgs; + } + + private boolean hasTrimmedAnnotation(Annotation[] annotations) { + for (Annotation annotation : annotations) { + if (annotation.annotationType().equals(Trimmed.class)) { + return true; + } + } + return false; + } } diff --git a/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/annotation/EnableStringTrimming.java b/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/annotation/EnableStringTrimming.java index 8c06d65..69a5546 100644 --- a/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/annotation/EnableStringTrimming.java +++ b/3-0-spring-framework/3-3-0-enable-string-trimming/src/main/java/com/bobocode/annotation/EnableStringTrimming.java @@ -1,8 +1,18 @@ package com.bobocode.annotation; +import com.bobocode.StringTrimmingConfiguration; +import org.springframework.context.annotation.Import; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + /** * Annotation that can be placed on configuration class to import {@link StringTrimmingConfiguration} */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Import(StringTrimmingConfiguration.class) public @interface EnableStringTrimming { -//todo: Implement EnableStringTrimming annotation according to javadoc }