diff --git a/jakarta-ee/pom.xml b/jakarta-ee/pom.xml new file mode 100644 index 0000000000..074ca1eec8 --- /dev/null +++ b/jakarta-ee/pom.xml @@ -0,0 +1,111 @@ + + 4.0.0 + + com.baeldung + mvc-2.0 + 1.0-SNAPSHOT + war + + mvc-2.0 + + + 9.0.0 + 2.0.0 + 2.0.0 + 5.8.2 + C:/glassfish6 + admin + mvn-domain + 1.10.19 + + ${local.glassfish.home}\\domains\\${local.glassfish.domain}\\config\\domain-passwords + + + + + + jakarta.platform + jakarta.jakartaee-web-api + ${jakartaee-api.version} + provided + + + + jakarta.mvc + jakarta.mvc-api + ${jakarta.mvc-api.version} + + + + org.eclipse.krazo + krazo-jersey + ${krazo.version} + + + org.junit.jupiter + junit-jupiter-api + ${junit.jupiter.version} + test + + + org.mockito + mockito-all + ${mockito.version} + test + + + + + + mvc-2.0 + + + org.glassfish.maven.plugin + maven-glassfish-plugin + 2.1 + + ${local.glassfish.home} + admin + + password + + + ${local.glassfish.domain} + 8080 + 4848 + + + + + ${project.artifactId} + target/${project.build.finalName}.war + + + + true + false + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-war-plugin + + false + + + + + diff --git a/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/User.java b/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/User.java new file mode 100644 index 0000000000..a2253b6aa6 --- /dev/null +++ b/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/User.java @@ -0,0 +1,84 @@ +package com.baeldung.eclipse.krazo; + +import jakarta.enterprise.context.RequestScoped; +import jakarta.inject.Named; +import jakarta.mvc.RedirectScoped; +import jakarta.mvc.binding.MvcBinding; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Null; +import jakarta.validation.constraints.Size; +import jakarta.ws.rs.FormParam; + +import java.io.Serializable; + +@Named("user") +@RedirectScoped +public class User implements Serializable { + @MvcBinding + @Null + private String id; + + @MvcBinding + @NotNull + @Size(min = 1, message = "Name cannot be blank") + @FormParam("name") + private String name; + + @MvcBinding + @Min(value = 18, message = "The minimum age of the user should be 18 years") + @FormParam("age") + private int age; + + @MvcBinding + @Email(message = "The email cannot be blank and should be in a valid format") + @Size(min=3, message = "Email cannot be empty") + @FormParam("email") + private String email; + + @MvcBinding + @Null + @FormParam("phone") + private String phone; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } +} diff --git a/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/UserApplication.java b/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/UserApplication.java new file mode 100644 index 0000000000..5a272806cb --- /dev/null +++ b/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/UserApplication.java @@ -0,0 +1,11 @@ +package com.baeldung.eclipse.krazo; + +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.core.Application; + +/** + * Default JAX-RS application listening on /app + */ +@ApplicationPath("/app") +public class UserApplication extends Application { +} diff --git a/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/UserController.java b/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/UserController.java new file mode 100644 index 0000000000..92ddf73571 --- /dev/null +++ b/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/UserController.java @@ -0,0 +1,85 @@ +package com.baeldung.eclipse.krazo; + +import jakarta.inject.Inject; +import jakarta.mvc.Controller; +import jakarta.mvc.Models; +import jakarta.mvc.binding.BindingResult; +import jakarta.mvc.security.CsrfProtected; +import jakarta.validation.Valid; +import jakarta.ws.rs.BeanParam; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * The class contains two controllers and a REST API + */ +@Path("users") +public class UserController { + @Inject + private BindingResult bindingResult; + + private static final List users = new ArrayList<>(); + + @Inject + private Models models; + + /** + * This is a controller. It displays a initial form to the user. + * @return The view name + */ + @GET + @Controller + public String showForm() { + return "user.jsp"; + } + + /** + * The method handles the form submits + * Handles HTTP POST and is CSRF protected. The client invoking this controller should provide a CSRF token. + * @param user The user details that has to be stored + * @return Returns a view name + */ + @POST + @Controller + @CsrfProtected + public String saveUser(@Valid @BeanParam User user) { + if (bindingResult.isFailed()) { + models.put("errors", bindingResult.getAllErrors()); + return "user.jsp"; + } + String id = UUID.randomUUID().toString(); + user.setId(id); + users.add(user); + return "redirect:users/success"; + } + + /** + * Handles a redirect view + * @return The view name + */ + @GET + @Controller + @Path("success") + public String saveUserSuccess() { + return "success.jsp"; + } + + /** + * The REST API that returns all the user details in the JSON format + * @return The list of users that are saved. The List is converted into Json Array. + * If no user is present a empty array is returned + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + public List getUsers() { + return users; + } + +} diff --git a/jakarta-ee/src/main/webapp/WEB-INF/beans.xml b/jakarta-ee/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 0000000000..d068fbd3e4 --- /dev/null +++ b/jakarta-ee/src/main/webapp/WEB-INF/beans.xml @@ -0,0 +1,6 @@ + + + diff --git a/jakarta-ee/src/main/webapp/WEB-INF/views/success.jsp b/jakarta-ee/src/main/webapp/WEB-INF/views/success.jsp new file mode 100644 index 0000000000..19d45e46ba --- /dev/null +++ b/jakarta-ee/src/main/webapp/WEB-INF/views/success.jsp @@ -0,0 +1,47 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + + + + MVC 2.0 + + + + + + + + + + + + Baeldung - Eclipse Krazo + + + + + + + + + + + + + User created successfully! + + + + + + + + + + + + + \ No newline at end of file diff --git a/jakarta-ee/src/main/webapp/WEB-INF/views/user.jsp b/jakarta-ee/src/main/webapp/WEB-INF/views/user.jsp new file mode 100644 index 0000000000..a36655950d --- /dev/null +++ b/jakarta-ee/src/main/webapp/WEB-INF/views/user.jsp @@ -0,0 +1,89 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + + + + MVC 2.0 + + + + + + + + + + + + Baeldung - Eclipse Krazo + + + + + + + + + + + User Details + + + + + + + ${error.paramName} + ${error.message} + + + + + + + Name + + + + + + Age + + + + + + Email + + + + + + Phone + + + + + + + + Create + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/jakarta-ee/src/main/webapp/styles.css b/jakarta-ee/src/main/webapp/styles.css new file mode 100644 index 0000000000..9cc9e62f12 --- /dev/null +++ b/jakarta-ee/src/main/webapp/styles.css @@ -0,0 +1,28 @@ +body, html { + font-family: Raleway, serif; + font-weight: 300; +} + +.bg-dark { + background-color: #63b175 !important; + font-weight: 600 !important; +} + +body { + padding-top: 80px; +} + +@media (max-width: 979px) { + body { + padding-top: 0; + } +} + +label { + font-weight: bold; +} + +.hr-dark { + border-top: 2px solid #000; + margin-bottom: 20px; +} \ No newline at end of file diff --git a/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/AppTest.java b/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/AppTest.java new file mode 100644 index 0000000000..6934d1fca2 --- /dev/null +++ b/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/AppTest.java @@ -0,0 +1,16 @@ +package com.baeldung.eclipse.krazo; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Dummy Test + */ +public class AppTest { + + @Test + public void test() { + assertTrue(true); + } +} diff --git a/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/UserControllerUnitTest.java b/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/UserControllerUnitTest.java new file mode 100644 index 0000000000..5e79924ed7 --- /dev/null +++ b/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/UserControllerUnitTest.java @@ -0,0 +1,116 @@ +package com.baeldung.eclipse.krazo; + +import com.baeldung.eclipse.krazo.User; +import com.baeldung.eclipse.krazo.UserController; +import jakarta.mvc.Models; +import jakarta.mvc.binding.BindingResult; +import org.eclipse.krazo.core.ModelsImpl; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.when; + +/** + * The class contains unit tests. We do only unit tests. Most of the classes are mocked + */ +@DisplayName("Eclipse Krazo MVC 2.0 Test Suite") +class UserControllerUnitTest { + + @InjectMocks + UserController userController = new UserController(); + + @Mock + Models models; + + @Mock + BindingResult bindingResult; + + @BeforeEach + public void setUpClass() { + MockitoAnnotations.initMocks(this); + } + + @Test + @DisplayName("Test Show Form") + void whenShowForm_thenReturnViewName() { + assertNotNull(userController.showForm()); + assertEquals("user.jsp", userController.showForm()); + } + + @Test + @DisplayName("Test Save User Success") + void whenSaveUser_thenReturnSuccess() { + when(bindingResult.isFailed()).thenReturn(false); + + User user = new User(); + + assertNotNull(userController.saveUser(user)); + assertDoesNotThrow(() -> userController.saveUser(user)); + assertEquals("redirect:users/success", userController.saveUser(user)); + } + + @Test + @DisplayName("Test Save User Binding Errors") + void whenSaveUser_thenReturnError() { + when(bindingResult.isFailed()).thenReturn(true); + Models testModels = new ModelsImpl(); + when(models.put(anyString(), any())).thenReturn(testModels); + User user = getUser(); + assertNotNull(userController.saveUser(user)); + assertDoesNotThrow(() -> userController.saveUser(user)); + assertEquals("user.jsp", userController.saveUser(user)); + } + + @Test + @DisplayName("Test Save User Success View") + void whenSaveUserSuccess_thenRedirectSuccess() { + assertNotNull(userController.saveUserSuccess()); + assertDoesNotThrow(() -> userController.saveUserSuccess()); + assertEquals("success.jsp", userController.saveUserSuccess()); + } + + @Test + @DisplayName("Test Get Users API") + void whenGetUser_thenReturnUsers() { + when(bindingResult.isFailed()).thenReturn(false); + + User user= getUser(); + + assertNotNull(user); + assertEquals(30, user.getAge()); + assertEquals("john doe", user.getName()); + assertEquals("anymail", user.getEmail()); + assertEquals("99887766554433", user.getPhone()); + assertEquals("1", user.getId()); + + userController.saveUser(user); + userController.saveUser(user); + userController.saveUser(user); + + assertNotNull(userController.getUsers()); + assertDoesNotThrow(() -> userController.getUsers()); + assertEquals(3, userController.getUsers().size()); + + } + + private User getUser() { + User user = new User(); + user.setId("1"); + user.setName("john doe"); + user.setAge(30); + user.setEmail("anymail"); + user.setPhone("99887766554433"); + return user; + } + +} diff --git a/pom.xml b/pom.xml index 197e946974..b6767c629b 100644 --- a/pom.xml +++ b/pom.xml @@ -462,6 +462,7 @@ jaxb jee-7 jee-7-security + jakarta-ee jersey jgit jgroups @@ -555,9 +556,9 @@ rxjava-observables rxjava-operators - atomikos - reactive-systems - slack + atomikos + reactive-systems + slack @@ -945,6 +946,7 @@ jaxb jee-7 jee-7-security + jakarta-ee jersey jgit jgroups @@ -1038,9 +1040,9 @@ rxjava-observables rxjava-operators - atomikos - reactive-systems - slack + atomikos + reactive-systems + slack @@ -1311,43 +1313,43 @@ - core-java-modules/core-java-9 - core-java-modules/core-java-9-improvements - core-java-modules/core-java-9-jigsaw + core-java-modules/core-java-9 + core-java-modules/core-java-9-improvements + core-java-modules/core-java-9-jigsaw - core-java-modules/core-java-9-streams - core-java-modules/core-java-10 - core-java-modules/core-java-11 - core-java-modules/core-java-11-2 - - - - - core-java-modules/core-java-collections-set - core-java-modules/core-java-collections-maps-4 - core-java-modules/core-java-date-operations-1 - core-java-modules/core-java-datetime-conversion - core-java-modules/core-java-datetime-string - core-java-modules/core-java-io-conversions-2 - core-java-modules/core-java-jpms - core-java-modules/core-java-os - core-java-modules/core-java-string-algorithms-3 - core-java-modules/core-java-string-operations-3 - core-java-modules/core-java-string-operations-4 - core-java-modules/core-java-time-measurements - core-java-modules/core-java-networking-3 - core-java-modules/multimodulemavenproject - ddd-modules - httpclient-2 - libraries-concurrency - persistence-modules/sirix - persistence-modules/spring-data-cassandra-2 - quarkus-vs-springboot - quarkus-jandex - spring-boot-modules/spring-boot-cassandre - spring-boot-modules/spring-boot-camel - testing-modules/testing-assertions - persistence-modules/fauna + core-java-modules/core-java-9-streams + core-java-modules/core-java-10 + core-java-modules/core-java-11 + core-java-modules/core-java-11-2 + + + + + core-java-modules/core-java-collections-set + core-java-modules/core-java-collections-maps-4 + core-java-modules/core-java-date-operations-1 + core-java-modules/core-java-datetime-conversion + core-java-modules/core-java-datetime-string + core-java-modules/core-java-io-conversions-2 + core-java-modules/core-java-jpms + core-java-modules/core-java-os + core-java-modules/core-java-string-algorithms-3 + core-java-modules/core-java-string-operations-3 + core-java-modules/core-java-string-operations-4 + core-java-modules/core-java-time-measurements + core-java-modules/core-java-networking-3 + core-java-modules/multimodulemavenproject + ddd-modules + httpclient-2 + libraries-concurrency + persistence-modules/sirix + persistence-modules/spring-data-cassandra-2 + quarkus-vs-springboot + quarkus-jandex + spring-boot-modules/spring-boot-cassandre + spring-boot-modules/spring-boot-camel + testing-modules/testing-assertions + persistence-modules/fauna