From 3364e1ccad8e0247f8cf1f3fed7f3673a431c10a Mon Sep 17 00:00:00 2001 From: Nguyen Nam Thai Date: Tue, 6 Mar 2018 15:37:37 +0700 Subject: [PATCH 1/7] Initial commit for Apache Tika --- apache-tika/.gitignore | 3 + apache-tika/pom.xml | 25 ++++++ .../java/com/baeldung/tika/TikaAnalysis.java | 67 +++++++++++++++ .../java/com/baeldung/tika/TikaUnitTest.java | 81 ++++++++++++++++++ apache-tika/src/test/resources/tika.txt | Bin 0 -> 36305 bytes apache-tika/src/test/resources/tika.xlsx | Bin 0 -> 8348 bytes pom.xml | 3 +- 7 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 apache-tika/.gitignore create mode 100644 apache-tika/pom.xml create mode 100644 apache-tika/src/main/java/com/baeldung/tika/TikaAnalysis.java create mode 100644 apache-tika/src/test/java/com/baeldung/tika/TikaUnitTest.java create mode 100644 apache-tika/src/test/resources/tika.txt create mode 100644 apache-tika/src/test/resources/tika.xlsx diff --git a/apache-tika/.gitignore b/apache-tika/.gitignore new file mode 100644 index 0000000000..5f88621edc --- /dev/null +++ b/apache-tika/.gitignore @@ -0,0 +1,3 @@ +*.docx +temp.xls +temp.xlsx \ No newline at end of file diff --git a/apache-tika/pom.xml b/apache-tika/pom.xml new file mode 100644 index 0000000000..34013dee89 --- /dev/null +++ b/apache-tika/pom.xml @@ -0,0 +1,25 @@ + + 4.0.0 + com.baeldung + apache-tika + 0.0.1-SNAPSHOT + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + 1.17 + + + + + org.apache.tika + tika-parsers + ${tika.version} + + + \ No newline at end of file diff --git a/apache-tika/src/main/java/com/baeldung/tika/TikaAnalysis.java b/apache-tika/src/main/java/com/baeldung/tika/TikaAnalysis.java new file mode 100644 index 0000000000..85eafc7c08 --- /dev/null +++ b/apache-tika/src/main/java/com/baeldung/tika/TikaAnalysis.java @@ -0,0 +1,67 @@ +package com.baeldung.tika; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.tika.Tika; +import org.apache.tika.detect.DefaultDetector; +import org.apache.tika.detect.Detector; +import org.apache.tika.exception.TikaException; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.mime.MediaType; +import org.apache.tika.parser.AutoDetectParser; +import org.apache.tika.parser.ParseContext; +import org.apache.tika.parser.Parser; +import org.apache.tika.sax.BodyContentHandler; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +public class TikaAnalysis { + public static String detectDocTypeUsingDetector(InputStream stream) throws IOException { + Detector detector = new DefaultDetector(); + Metadata metadata = new Metadata(); + + MediaType mediaType = detector.detect(stream, metadata); + return mediaType.toString(); + } + + public static String detectDocTypeUsingFacade(InputStream stream) throws IOException { + Tika tika = new Tika(); + String mediaType = tika.detect(stream); + return mediaType; + } + + public static String extractContentUsingParser(InputStream stream) throws IOException, TikaException, SAXException { + Parser parser = new AutoDetectParser(); + ContentHandler handler = new BodyContentHandler(); + Metadata metadata = new Metadata(); + ParseContext context = new ParseContext(); + + parser.parse(stream, handler, metadata, context); + return handler.toString(); + } + + public static String extractContentUsingFacade(InputStream stream) throws IOException, TikaException { + Tika tika = new Tika(); + String content = tika.parseToString(stream); + return content; + } + + public static Metadata extractMetadatatUsingParser(InputStream stream) throws IOException, SAXException, TikaException { + Parser parser = new AutoDetectParser(); + ContentHandler handler = new BodyContentHandler(); + Metadata metadata = new Metadata(); + ParseContext context = new ParseContext(); + + parser.parse(stream, handler, metadata, context); + return metadata; + } + + public static Metadata extractMetadatatUsingFacade(InputStream stream) throws IOException, TikaException { + Tika tika = new Tika(); + Metadata metadata = new Metadata(); + + tika.parse(stream, metadata); + return metadata; + } +} diff --git a/apache-tika/src/test/java/com/baeldung/tika/TikaUnitTest.java b/apache-tika/src/test/java/com/baeldung/tika/TikaUnitTest.java new file mode 100644 index 0000000000..555a796d59 --- /dev/null +++ b/apache-tika/src/test/java/com/baeldung/tika/TikaUnitTest.java @@ -0,0 +1,81 @@ +package com.baeldung.tika; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.tika.exception.TikaException; +import org.apache.tika.metadata.Metadata; +import org.junit.Test; +import org.xml.sax.SAXException; + +public class TikaUnitTest { + private ClassLoader loader = this.getClass().getClassLoader(); + + @Test + public void whenUsingDetector_thenDocumentTypeIsReturned() throws IOException { + InputStream stream = loader.getResourceAsStream("tika.txt"); + String mediaType = TikaAnalysis.detectDocTypeUsingDetector(stream); + + assertEquals("application/pdf", mediaType); + + stream.close(); + } + + @Test + public void whenUsingFacade_thenDocumentTypeIsReturned() throws IOException { + InputStream stream = loader.getResourceAsStream("tika.txt"); + String mediaType = TikaAnalysis.detectDocTypeUsingFacade(stream); + + assertEquals("application/pdf", mediaType); + + stream.close(); + } + + @Test + public void whenUsingParser_thenContentIsReturned() throws IOException, TikaException, SAXException { + InputStream stream = loader.getResourceAsStream("tika.docx"); + String content = TikaAnalysis.extractContentUsingParser(stream); + + assertThat(content, containsString("Apache Tika - a content analysis toolkit")); + assertThat(content, containsString("detects and extracts metadata and text")); + + stream.close(); + } + + @Test + public void whenUsingFacade_thenContentIsReturned() throws IOException, TikaException { + InputStream stream = loader.getResourceAsStream("tika.docx"); + String content = TikaAnalysis.extractContentUsingFacade(stream); + + assertThat(content, containsString("Apache Tika - a content analysis toolkit")); + assertThat(content, containsString("detects and extracts metadata and text")); + + stream.close(); + } + + @Test + public void whenUsingParser_thenMetadataIsReturned() throws IOException, TikaException, SAXException { + InputStream stream = loader.getResourceAsStream("tika.xlsx"); + Metadata metadata = TikaAnalysis.extractMetadatatUsingParser(stream); + + assertEquals("org.apache.tika.parser.DefaultParser", metadata.get("X-Parsed-By")); + assertEquals("Microsoft Office User", metadata.get("Author")); + + stream.close(); + } + + @Test + public void whenUsingFacade_thenMetadataIsReturned() throws IOException, TikaException { + InputStream stream = loader.getResourceAsStream("tika.xlsx"); + Metadata metadata = TikaAnalysis.extractMetadatatUsingFacade(stream); + + assertEquals("org.apache.tika.parser.DefaultParser", metadata.get("X-Parsed-By")); + assertEquals("Microsoft Office User", metadata.get("Author")); + + stream.close(); + } +} diff --git a/apache-tika/src/test/resources/tika.txt b/apache-tika/src/test/resources/tika.txt new file mode 100644 index 0000000000000000000000000000000000000000..26923836de7d3e313047abfc892d503246616188 GIT binary patch literal 36305 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�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 J6v`j}{tt9&U~T{a literal 0 HcmV?d00001 diff --git a/pom.xml b/pom.xml index 75cf4b84b8..1731e1661c 100644 --- a/pom.xml +++ b/pom.xml @@ -38,6 +38,7 @@ apache-cxf apache-fop apache-poi + apache-tika apache-thrift autovalue axon @@ -383,4 +384,4 @@ - \ No newline at end of file + From a079f521ebb977ae078e9136387c68a7ebd3391e Mon Sep 17 00:00:00 2001 From: Nguyen Nam Thai Date: Tue, 6 Mar 2018 15:40:01 +0700 Subject: [PATCH 2/7] Add a test resource for Apache Tika --- apache-tika/.gitignore | 3 --- apache-tika/src/test/resources/tika.docx | Bin 0 -> 12811 bytes 2 files changed, 3 deletions(-) delete mode 100644 apache-tika/.gitignore create mode 100644 apache-tika/src/test/resources/tika.docx diff --git a/apache-tika/.gitignore b/apache-tika/.gitignore deleted file mode 100644 index 5f88621edc..0000000000 --- a/apache-tika/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.docx -temp.xls -temp.xlsx \ No newline at end of file diff --git a/apache-tika/src/test/resources/tika.docx b/apache-tika/src/test/resources/tika.docx new file mode 100644 index 0000000000000000000000000000000000000000..0a01ccef55dfdff806e5ad9ef8b1174d2f001d16 GIT binary patch literal 12811 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 literal 0 HcmV?d00001 From bbe6f609167dfb6862ebec174a68beff727a1f91 Mon Sep 17 00:00:00 2001 From: Nguyen Nam Thai Date: Tue, 6 Mar 2018 15:53:17 +0700 Subject: [PATCH 3/7] Remove the ending line of the pom.xml file --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1731e1661c..10abee4016 100644 --- a/pom.xml +++ b/pom.xml @@ -384,4 +384,4 @@ - + \ No newline at end of file From 734ace918d9e22422261f4a4e1fa22893e3f4b7c Mon Sep 17 00:00:00 2001 From: Nguyen Nam Thai Date: Tue, 6 Mar 2018 17:58:13 +0700 Subject: [PATCH 4/7] Refactor the tests --- .../test/java/com/baeldung/tika/TikaUnitTest.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/apache-tika/src/test/java/com/baeldung/tika/TikaUnitTest.java b/apache-tika/src/test/java/com/baeldung/tika/TikaUnitTest.java index 555a796d59..f8c2372d1f 100644 --- a/apache-tika/src/test/java/com/baeldung/tika/TikaUnitTest.java +++ b/apache-tika/src/test/java/com/baeldung/tika/TikaUnitTest.java @@ -13,11 +13,9 @@ import org.junit.Test; import org.xml.sax.SAXException; public class TikaUnitTest { - private ClassLoader loader = this.getClass().getClassLoader(); - @Test public void whenUsingDetector_thenDocumentTypeIsReturned() throws IOException { - InputStream stream = loader.getResourceAsStream("tika.txt"); + InputStream stream = this.getClass().getClassLoader().getResourceAsStream("tika.txt"); String mediaType = TikaAnalysis.detectDocTypeUsingDetector(stream); assertEquals("application/pdf", mediaType); @@ -27,7 +25,7 @@ public class TikaUnitTest { @Test public void whenUsingFacade_thenDocumentTypeIsReturned() throws IOException { - InputStream stream = loader.getResourceAsStream("tika.txt"); + InputStream stream = this.getClass().getClassLoader().getResourceAsStream("tika.txt"); String mediaType = TikaAnalysis.detectDocTypeUsingFacade(stream); assertEquals("application/pdf", mediaType); @@ -37,7 +35,7 @@ public class TikaUnitTest { @Test public void whenUsingParser_thenContentIsReturned() throws IOException, TikaException, SAXException { - InputStream stream = loader.getResourceAsStream("tika.docx"); + InputStream stream = this.getClass().getClassLoader().getResourceAsStream("tika.docx"); String content = TikaAnalysis.extractContentUsingParser(stream); assertThat(content, containsString("Apache Tika - a content analysis toolkit")); @@ -48,7 +46,7 @@ public class TikaUnitTest { @Test public void whenUsingFacade_thenContentIsReturned() throws IOException, TikaException { - InputStream stream = loader.getResourceAsStream("tika.docx"); + InputStream stream = this.getClass().getClassLoader().getResourceAsStream("tika.docx"); String content = TikaAnalysis.extractContentUsingFacade(stream); assertThat(content, containsString("Apache Tika - a content analysis toolkit")); @@ -59,7 +57,7 @@ public class TikaUnitTest { @Test public void whenUsingParser_thenMetadataIsReturned() throws IOException, TikaException, SAXException { - InputStream stream = loader.getResourceAsStream("tika.xlsx"); + InputStream stream = this.getClass().getClassLoader().getResourceAsStream("tika.xlsx"); Metadata metadata = TikaAnalysis.extractMetadatatUsingParser(stream); assertEquals("org.apache.tika.parser.DefaultParser", metadata.get("X-Parsed-By")); @@ -70,7 +68,7 @@ public class TikaUnitTest { @Test public void whenUsingFacade_thenMetadataIsReturned() throws IOException, TikaException { - InputStream stream = loader.getResourceAsStream("tika.xlsx"); + InputStream stream = this.getClass().getClassLoader().getResourceAsStream("tika.xlsx"); Metadata metadata = TikaAnalysis.extractMetadatatUsingFacade(stream); assertEquals("org.apache.tika.parser.DefaultParser", metadata.get("X-Parsed-By")); From 84080c9e955fafc9b56ab8079a520995c669af44 Mon Sep 17 00:00:00 2001 From: Chris Oberle Date: Sat, 10 Mar 2018 07:06:26 -0500 Subject: [PATCH 5/7] BAEL-1533 - Making a Spring MVC Form Remember Values --- pom.xml | 3 +- spring-5/pom.xml | 437 +++++++++--------- .../README.md | 0 .../pom.xml | 4 +- .../ApplicationConfiguration.java | 0 .../configuration/WebInitializer.java | 0 .../controller/CustomerController.java | 0 .../controller/EmployeeController.java | 0 .../controller/FileUploadController.java | 0 .../controller/UserController.java | 0 .../springmvcforms/domain/Customer.java | 0 .../springmvcforms/domain/Employee.java | 0 .../baeldung/springmvcforms/domain/User.java | 0 .../FileUploadExceptionAdvice.java | 0 .../validator/CustomerValidator.java | 0 .../src/main/webapp/WEB-INF/html/user.html | 0 .../webapp/WEB-INF/views/customerHome.jsp | 0 .../webapp/WEB-INF/views/customerView.jsp | 0 .../webapp/WEB-INF/views/employeeHome.jsp | 0 .../webapp/WEB-INF/views/employeeView.jsp | 0 .../src/main/webapp/WEB-INF/views/error.jsp | 0 .../src/main/webapp/WEB-INF/views/file.jsp | 0 .../src/main/webapp/css/user.css | 0 .../src/main/webapp/js/app.js | 0 spring-mvc-forms-thymeleaf/pom.xml | 73 +++ .../com/baeldung/sessionattrs/Config.java | 88 ++-- .../sessionattrs/SessionAttrsApplication.java | 0 .../TodoControllerWithScopedProxy.java | 90 ++-- .../TodoControllerWithSessionAttributes.java | 110 ++--- .../com/baeldung/sessionattrs/TodoItem.java | 78 ++-- .../com/baeldung/sessionattrs/TodoList.java | 16 +- .../src/main/resources/application.properties | 3 + .../templates/sessionattrs/index.html | 52 +-- .../sessionattrs/scopedproxyform.html | 52 +-- .../sessionattrs/scopedproxytodos.html | 94 ++-- .../sessionattrs/sessionattributesform.html | 52 +-- .../sessionattrs/sessionattributestodos.html | 94 ++-- .../SessionAttrsApplicationTest.java | 2 +- .../com/baeldung/sessionattrs/TestConfig.java | 34 +- .../TodoControllerWithScopedProxyTest.java | 136 +++--- ...doControllerWithSessionAttributesTest.java | 136 +++--- 41 files changed, 819 insertions(+), 735 deletions(-) rename {spring-mvc-forms => spring-mvc-forms-jsp}/README.md (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/pom.xml (97%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/java/com/baeldung/springmvcforms/configuration/ApplicationConfiguration.java (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/java/com/baeldung/springmvcforms/controller/CustomerController.java (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/java/com/baeldung/springmvcforms/controller/EmployeeController.java (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/java/com/baeldung/springmvcforms/controller/FileUploadController.java (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/java/com/baeldung/springmvcforms/controller/UserController.java (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/java/com/baeldung/springmvcforms/domain/Customer.java (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/java/com/baeldung/springmvcforms/domain/Employee.java (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/java/com/baeldung/springmvcforms/domain/User.java (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/java/com/baeldung/springmvcforms/interceptor/FileUploadExceptionAdvice.java (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/java/com/baeldung/springmvcforms/validator/CustomerValidator.java (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/webapp/WEB-INF/html/user.html (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/webapp/WEB-INF/views/customerHome.jsp (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/webapp/WEB-INF/views/customerView.jsp (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/webapp/WEB-INF/views/employeeHome.jsp (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/webapp/WEB-INF/views/employeeView.jsp (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/webapp/WEB-INF/views/error.jsp (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/webapp/WEB-INF/views/file.jsp (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/webapp/css/user.css (100%) rename {spring-mvc-forms => spring-mvc-forms-jsp}/src/main/webapp/js/app.js (100%) create mode 100644 spring-mvc-forms-thymeleaf/pom.xml rename {spring-5 => spring-mvc-forms-thymeleaf}/src/main/java/com/baeldung/sessionattrs/Config.java (97%) rename {spring-5 => spring-mvc-forms-thymeleaf}/src/main/java/com/baeldung/sessionattrs/SessionAttrsApplication.java (100%) rename {spring-5 => spring-mvc-forms-thymeleaf}/src/main/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxy.java (96%) rename {spring-5 => spring-mvc-forms-thymeleaf}/src/main/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributes.java (97%) rename {spring-5 => spring-mvc-forms-thymeleaf}/src/main/java/com/baeldung/sessionattrs/TodoItem.java (95%) rename {spring-5 => spring-mvc-forms-thymeleaf}/src/main/java/com/baeldung/sessionattrs/TodoList.java (94%) create mode 100644 spring-mvc-forms-thymeleaf/src/main/resources/application.properties rename {spring-5 => spring-mvc-forms-thymeleaf}/src/main/resources/templates/sessionattrs/index.html (97%) rename {spring-5 => spring-mvc-forms-thymeleaf}/src/main/resources/templates/sessionattrs/scopedproxyform.html (97%) rename {spring-5 => spring-mvc-forms-thymeleaf}/src/main/resources/templates/sessionattrs/scopedproxytodos.html (96%) rename {spring-5 => spring-mvc-forms-thymeleaf}/src/main/resources/templates/sessionattrs/sessionattributesform.html (97%) rename {spring-5 => spring-mvc-forms-thymeleaf}/src/main/resources/templates/sessionattrs/sessionattributestodos.html (96%) rename spring-5/src/test/java/com/baeldung/sessionattrs/SessionAttrsApplicationIntegrationTest.java => spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/SessionAttrsApplicationTest.java (85%) rename {spring-5 => spring-mvc-forms-thymeleaf}/src/test/java/com/baeldung/sessionattrs/TestConfig.java (97%) rename spring-5/src/test/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxyIntegrationTest.java => spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxyTest.java (91%) rename spring-5/src/test/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributesIntegrationTest.java => spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributesTest.java (95%) diff --git a/pom.xml b/pom.xml index 70a3bbc5b4..205d42858a 100644 --- a/pom.xml +++ b/pom.xml @@ -199,7 +199,8 @@ spring-ldap spring-mockito spring-mvc-email - spring-mvc-forms + spring-mvc-forms-jsp + spring-mvc-forms-thymeleaf spring-mvc-java spring-mvc-tiles spring-mvc-velocity diff --git a/spring-5/pom.xml b/spring-5/pom.xml index b4e6e684ad..f8bad72c51 100644 --- a/spring-5/pom.xml +++ b/spring-5/pom.xml @@ -1,215 +1,222 @@ - - - 4.0.0 - - com.baeldung - spring-5 - 0.0.1-SNAPSHOT - jar - - spring-5 - spring 5 sample project about new features - - - org.springframework.boot - spring-boot-starter-parent - 2.0.0.RELEASE - - - - - - org.springframework.boot - spring-boot-starter-data-jpa - - - org.springframework.boot - spring-boot-starter-security - - - org.springframework.boot - spring-boot-starter-validation - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-webflux - - - org.springframework.boot - spring-boot-starter-hateoas - - - org.springframework.boot - spring-boot-starter-thymeleaf - - - org.projectreactor - reactor-spring - ${reactor-spring.version} - - - javax.json.bind - javax.json.bind-api - - - org.apache.geronimo.specs - geronimo-json_1.1_spec - ${geronimo-json_1.1_spec.version} - - - org.apache.johnzon - johnzon-jsonb - ${johnzon.version} - - - - org.apache.commons - commons-lang3 - - - - - - org.springframework.boot - spring-boot-devtools - runtime - - - com.h2database - h2 - runtime - - - - org.springframework - spring-test - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.security - spring-security-test - test - - - - org.apache.commons - commons-collections4 - 4.1 - test - - - - org.junit.jupiter - junit-jupiter-api - - - org.junit.jupiter - junit-jupiter-engine - test - - - org.junit.platform - junit-platform-surefire-provider - ${junit.platform.version} - test - - - org.junit.platform - junit-platform-runner - ${junit.platform.version} - test - - - - org.springframework.restdocs - spring-restdocs-mockmvc - test - - - org.springframework.restdocs - spring-restdocs-webtestclient - test - - - org.springframework.restdocs - spring-restdocs-restassured - test - - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - com.baeldung.Spring5Application - JAR - - - - - org.apache.maven.plugins - maven-surefire-plugin - - 3 - true - methods - true - - **/*IntegrationTest.java - **/*LiveTest.java - - - - - org.asciidoctor - asciidoctor-maven-plugin - ${asciidoctor-plugin.version} - - - generate-docs - package - - process-asciidoc - - - html - book - - ${snippetsDirectory} - - src/docs/asciidocs - target/generated-docs - - - - - - - - - UTF-8 - UTF-8 - 1.8 - 1.0.0 - 2.20 - 1.0.1.RELEASE - 1.1.3 - 1.0 - 1.5.6 - ${project.build.directory}/generated-snippets - - - + + + 4.0.0 + + com.baeldung + spring-5 + 0.0.1-SNAPSHOT + jar + + spring-5 + spring 5 sample project about new features + + + org.springframework.boot + spring-boot-starter-parent + 2.0.0.RELEASE + + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springframework.boot + spring-boot-starter-hateoas + + + org.projectreactor + reactor-spring + ${reactor-spring.version} + + + javax.json.bind + javax.json.bind-api + + + + + + + + + + + + + + + org.apache.geronimo.specs + geronimo-json_1.1_spec + ${geronimo-json_1.1_spec.version} + + + org.apache.johnzon + johnzon-jsonb + + + + org.apache.commons + commons-lang3 + + + + + + org.springframework.boot + spring-boot-devtools + runtime + + + com.h2database + h2 + runtime + + + + org.springframework + spring-test + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + test + + + + org.apache.commons + commons-collections4 + 4.1 + test + + + + org.junit.jupiter + junit-jupiter-api + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.platform + junit-platform-surefire-provider + ${junit.platform.version} + test + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + + + + org.springframework.restdocs + spring-restdocs-mockmvc + test + + + org.springframework.restdocs + spring-restdocs-webtestclient + test + + + org.springframework.restdocs + spring-restdocs-restassured + test + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.baeldung.Spring5Application + JAR + + + + + org.apache.maven.plugins + maven-surefire-plugin + + 3 + true + methods + true + + **/*IntegrationTest.java + **/*LiveTest.java + + + + + org.asciidoctor + asciidoctor-maven-plugin + ${asciidoctor-plugin.version} + + + generate-docs + package + + process-asciidoc + + + html + book + + ${snippetsDirectory} + + src/docs/asciidocs + target/generated-docs + + + + + + + + + UTF-8 + UTF-8 + 1.8 + 1.0.0 + 2.20 + 5.0.2.RELEASE + 1.0.1.RELEASE + 1.0 + 1.5.6 + ${project.build.directory}/generated-snippets + + + diff --git a/spring-mvc-forms/README.md b/spring-mvc-forms-jsp/README.md similarity index 100% rename from spring-mvc-forms/README.md rename to spring-mvc-forms-jsp/README.md diff --git a/spring-mvc-forms/pom.xml b/spring-mvc-forms-jsp/pom.xml similarity index 97% rename from spring-mvc-forms/pom.xml rename to spring-mvc-forms-jsp/pom.xml index e82a906112..bb666cff4f 100644 --- a/spring-mvc-forms/pom.xml +++ b/spring-mvc-forms-jsp/pom.xml @@ -6,9 +6,9 @@ 4.0.0 com.baeldung 0.1-SNAPSHOT - spring-mvc-forms + spring-mvc-forms-jsp - spring-mvc-forms + spring-mvc-forms-jsp war diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/ApplicationConfiguration.java b/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/configuration/ApplicationConfiguration.java similarity index 100% rename from spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/ApplicationConfiguration.java rename to spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/configuration/ApplicationConfiguration.java diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java b/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java similarity index 100% rename from spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java rename to spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/controller/CustomerController.java b/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/CustomerController.java similarity index 100% rename from spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/controller/CustomerController.java rename to spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/CustomerController.java diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/controller/EmployeeController.java b/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/EmployeeController.java similarity index 100% rename from spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/controller/EmployeeController.java rename to spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/EmployeeController.java diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/controller/FileUploadController.java b/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/FileUploadController.java similarity index 100% rename from spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/controller/FileUploadController.java rename to spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/FileUploadController.java diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/controller/UserController.java b/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/UserController.java similarity index 100% rename from spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/controller/UserController.java rename to spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/UserController.java diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/domain/Customer.java b/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/Customer.java similarity index 100% rename from spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/domain/Customer.java rename to spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/Customer.java diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/domain/Employee.java b/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/Employee.java similarity index 100% rename from spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/domain/Employee.java rename to spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/Employee.java diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/domain/User.java b/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/User.java similarity index 100% rename from spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/domain/User.java rename to spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/User.java diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/interceptor/FileUploadExceptionAdvice.java b/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/interceptor/FileUploadExceptionAdvice.java similarity index 100% rename from spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/interceptor/FileUploadExceptionAdvice.java rename to spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/interceptor/FileUploadExceptionAdvice.java diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/validator/CustomerValidator.java b/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/validator/CustomerValidator.java similarity index 100% rename from spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/validator/CustomerValidator.java rename to spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/validator/CustomerValidator.java diff --git a/spring-mvc-forms/src/main/webapp/WEB-INF/html/user.html b/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/html/user.html similarity index 100% rename from spring-mvc-forms/src/main/webapp/WEB-INF/html/user.html rename to spring-mvc-forms-jsp/src/main/webapp/WEB-INF/html/user.html diff --git a/spring-mvc-forms/src/main/webapp/WEB-INF/views/customerHome.jsp b/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/customerHome.jsp similarity index 100% rename from spring-mvc-forms/src/main/webapp/WEB-INF/views/customerHome.jsp rename to spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/customerHome.jsp diff --git a/spring-mvc-forms/src/main/webapp/WEB-INF/views/customerView.jsp b/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/customerView.jsp similarity index 100% rename from spring-mvc-forms/src/main/webapp/WEB-INF/views/customerView.jsp rename to spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/customerView.jsp diff --git a/spring-mvc-forms/src/main/webapp/WEB-INF/views/employeeHome.jsp b/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/employeeHome.jsp similarity index 100% rename from spring-mvc-forms/src/main/webapp/WEB-INF/views/employeeHome.jsp rename to spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/employeeHome.jsp diff --git a/spring-mvc-forms/src/main/webapp/WEB-INF/views/employeeView.jsp b/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/employeeView.jsp similarity index 100% rename from spring-mvc-forms/src/main/webapp/WEB-INF/views/employeeView.jsp rename to spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/employeeView.jsp diff --git a/spring-mvc-forms/src/main/webapp/WEB-INF/views/error.jsp b/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/error.jsp similarity index 100% rename from spring-mvc-forms/src/main/webapp/WEB-INF/views/error.jsp rename to spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/error.jsp diff --git a/spring-mvc-forms/src/main/webapp/WEB-INF/views/file.jsp b/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/file.jsp similarity index 100% rename from spring-mvc-forms/src/main/webapp/WEB-INF/views/file.jsp rename to spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/file.jsp diff --git a/spring-mvc-forms/src/main/webapp/css/user.css b/spring-mvc-forms-jsp/src/main/webapp/css/user.css similarity index 100% rename from spring-mvc-forms/src/main/webapp/css/user.css rename to spring-mvc-forms-jsp/src/main/webapp/css/user.css diff --git a/spring-mvc-forms/src/main/webapp/js/app.js b/spring-mvc-forms-jsp/src/main/webapp/js/app.js similarity index 100% rename from spring-mvc-forms/src/main/webapp/js/app.js rename to spring-mvc-forms-jsp/src/main/webapp/js/app.js diff --git a/spring-mvc-forms-thymeleaf/pom.xml b/spring-mvc-forms-thymeleaf/pom.xml new file mode 100644 index 0000000000..9238153847 --- /dev/null +++ b/spring-mvc-forms-thymeleaf/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + + com.baeldung + spring-mvc-forms-thymeleaf + 0.0.1-SNAPSHOT + jar + + spring-mvc-forms-thymeleaf + spring forms examples using thymeleaf + + + org.springframework.boot + spring-boot-starter-parent + 2.0.0.RELEASE + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + + org.springframework.boot + spring-boot-devtools + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.apache.maven.plugins + maven-surefire-plugin + + 3 + true + methods + true + + **/*IntegrationTest.java + **/*LiveTest.java + + + + + + + + UTF-8 + UTF-8 + + + diff --git a/spring-5/src/main/java/com/baeldung/sessionattrs/Config.java b/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/Config.java similarity index 97% rename from spring-5/src/main/java/com/baeldung/sessionattrs/Config.java rename to spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/Config.java index 9d5c9d9f42..7c9f1bf00b 100644 --- a/spring-5/src/main/java/com/baeldung/sessionattrs/Config.java +++ b/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/Config.java @@ -1,44 +1,44 @@ -package com.baeldung.sessionattrs; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Scope; -import org.springframework.context.annotation.ScopedProxyMode; -import org.springframework.core.Ordered; -import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import org.thymeleaf.templatemode.TemplateMode; -import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; -import org.thymeleaf.templateresolver.ITemplateResolver; - -@EnableWebMvc -@Configuration -public class Config implements WebMvcConfigurer { - - @Override - public void addViewControllers(ViewControllerRegistry registry) { - registry.addViewController("/").setViewName("index"); - registry.setOrder(Ordered.HIGHEST_PRECEDENCE); - } - - @Bean - @Scope( - value = WebApplicationContext.SCOPE_SESSION, - proxyMode = ScopedProxyMode.TARGET_CLASS) - public TodoList todos() { - return new TodoList(); - } - - @Bean - public ITemplateResolver templateResolver() { - ClassLoaderTemplateResolver resolver - = new ClassLoaderTemplateResolver(); - resolver.setPrefix("templates/sessionattrs/"); - resolver.setSuffix(".html"); - resolver.setTemplateMode(TemplateMode.HTML); - resolver.setCharacterEncoding("UTF-8"); - return resolver; - } -} +package com.baeldung.sessionattrs; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.core.Ordered; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.thymeleaf.templatemode.TemplateMode; +import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; +import org.thymeleaf.templateresolver.ITemplateResolver; + +@EnableWebMvc +@Configuration +public class Config implements WebMvcConfigurer { + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/").setViewName("index"); + registry.setOrder(Ordered.HIGHEST_PRECEDENCE); + } + + @Bean + @Scope( + value = WebApplicationContext.SCOPE_SESSION, + proxyMode = ScopedProxyMode.TARGET_CLASS) + public TodoList todos() { + return new TodoList(); + } + + @Bean + public ITemplateResolver templateResolver() { + ClassLoaderTemplateResolver resolver + = new ClassLoaderTemplateResolver(); + resolver.setPrefix("templates/sessionattrs/"); + resolver.setSuffix(".html"); + resolver.setTemplateMode(TemplateMode.HTML); + resolver.setCharacterEncoding("UTF-8"); + return resolver; + } +} diff --git a/spring-5/src/main/java/com/baeldung/sessionattrs/SessionAttrsApplication.java b/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/SessionAttrsApplication.java similarity index 100% rename from spring-5/src/main/java/com/baeldung/sessionattrs/SessionAttrsApplication.java rename to spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/SessionAttrsApplication.java diff --git a/spring-5/src/main/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxy.java b/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxy.java similarity index 96% rename from spring-5/src/main/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxy.java rename to spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxy.java index 0c3bd6c8b6..feedecf844 100644 --- a/spring-5/src/main/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxy.java +++ b/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxy.java @@ -1,45 +1,45 @@ -package com.baeldung.sessionattrs; - -import java.time.LocalDateTime; - -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; - -@Controller -@RequestMapping("/scopedproxy") -public class TodoControllerWithScopedProxy { - - private TodoList todos; - - public TodoControllerWithScopedProxy(TodoList todos) { - this.todos = todos; - } - - @GetMapping("/form") - public String showForm(Model model) { - if (!todos.isEmpty()) { - model.addAttribute("todo", todos.peekLast()); - } else { - model.addAttribute("todo", new TodoItem()); - } - - return "scopedproxyform"; - } - - @PostMapping("/form") - public String create(@ModelAttribute TodoItem todo) { - todo.setCreateDate(LocalDateTime.now()); - todos.add(todo); - return "redirect:/scopedproxy/todos.html"; - } - - @GetMapping("/todos.html") - public String list(Model model) { - model.addAttribute("todos", todos); - return "scopedproxytodos"; - } -} +package com.baeldung.sessionattrs; + +import java.time.LocalDateTime; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequestMapping("/scopedproxy") +public class TodoControllerWithScopedProxy { + + private TodoList todos; + + public TodoControllerWithScopedProxy(TodoList todos) { + this.todos = todos; + } + + @GetMapping("/form") + public String showForm(Model model) { + if (!todos.isEmpty()) { + model.addAttribute("todo", todos.peekLast()); + } else { + model.addAttribute("todo", new TodoItem()); + } + + return "scopedproxyform"; + } + + @PostMapping("/form") + public String create(@ModelAttribute TodoItem todo) { + todo.setCreateDate(LocalDateTime.now()); + todos.add(todo); + return "redirect:/scopedproxy/todos.html"; + } + + @GetMapping("/todos.html") + public String list(Model model) { + model.addAttribute("todos", todos); + return "scopedproxytodos"; + } +} diff --git a/spring-5/src/main/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributes.java b/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributes.java similarity index 97% rename from spring-5/src/main/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributes.java rename to spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributes.java index fc7e57b1db..99e0b46fc2 100644 --- a/spring-5/src/main/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributes.java +++ b/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributes.java @@ -1,55 +1,55 @@ -package com.baeldung.sessionattrs; - -import java.time.LocalDateTime; - -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.SessionAttributes; -import org.springframework.web.servlet.mvc.support.RedirectAttributes; -import org.springframework.web.servlet.view.RedirectView; - -@Controller -@RequestMapping("/sessionattributes") -@SessionAttributes("todos") -public class TodoControllerWithSessionAttributes { - - @GetMapping("/form") - public String showForm( - Model model, - @ModelAttribute("todos") TodoList todos) { - if (!todos.isEmpty()) { - model.addAttribute("todo", todos.peekLast()); - } else { - model.addAttribute("todo", new TodoItem()); - } - return "sessionattributesform"; - } - - @PostMapping("/form") - public RedirectView create( - @ModelAttribute TodoItem todo, - @ModelAttribute("todos") TodoList todos, - RedirectAttributes attributes) { - todo.setCreateDate(LocalDateTime.now()); - todos.add(todo); - attributes.addFlashAttribute("todos", todos); - return new RedirectView("/sessionattributes/todos.html"); - } - - @GetMapping("/todos.html") - public String list( - Model model, - @ModelAttribute("todos") TodoList todos) { - model.addAttribute("todos", todos); - return "sessionattributestodos"; - } - - @ModelAttribute("todos") - public TodoList todos() { - return new TodoList(); - } -} +package com.baeldung.sessionattrs; + +import java.time.LocalDateTime; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.SessionAttributes; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import org.springframework.web.servlet.view.RedirectView; + +@Controller +@RequestMapping("/sessionattributes") +@SessionAttributes("todos") +public class TodoControllerWithSessionAttributes { + + @GetMapping("/form") + public String showForm( + Model model, + @ModelAttribute("todos") TodoList todos) { + if (!todos.isEmpty()) { + model.addAttribute("todo", todos.peekLast()); + } else { + model.addAttribute("todo", new TodoItem()); + } + return "sessionattributesform"; + } + + @PostMapping("/form") + public RedirectView create( + @ModelAttribute TodoItem todo, + @ModelAttribute("todos") TodoList todos, + RedirectAttributes attributes) { + todo.setCreateDate(LocalDateTime.now()); + todos.add(todo); + attributes.addFlashAttribute("todos", todos); + return new RedirectView("/sessionattributes/todos.html"); + } + + @GetMapping("/todos.html") + public String list( + Model model, + @ModelAttribute("todos") TodoList todos) { + model.addAttribute("todos", todos); + return "sessionattributestodos"; + } + + @ModelAttribute("todos") + public TodoList todos() { + return new TodoList(); + } +} diff --git a/spring-5/src/main/java/com/baeldung/sessionattrs/TodoItem.java b/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoItem.java similarity index 95% rename from spring-5/src/main/java/com/baeldung/sessionattrs/TodoItem.java rename to spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoItem.java index 619d61d5f0..b8b24bc04d 100644 --- a/spring-5/src/main/java/com/baeldung/sessionattrs/TodoItem.java +++ b/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoItem.java @@ -1,39 +1,39 @@ -package com.baeldung.sessionattrs; - -import java.time.LocalDateTime; - -public class TodoItem { - - private String description; - private LocalDateTime createDate; - - public TodoItem(String description, LocalDateTime createDate) { - this.description = description; - this.createDate = createDate; - } - - public TodoItem() { - // default no arg constructor - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public LocalDateTime getCreateDate() { - return createDate; - } - - public void setCreateDate(LocalDateTime createDate) { - this.createDate = createDate; - } - - @Override - public String toString() { - return "TodoItem [description=" + description + ", createDate=" + createDate + "]"; - } -} +package com.baeldung.sessionattrs; + +import java.time.LocalDateTime; + +public class TodoItem { + + private String description; + private LocalDateTime createDate; + + public TodoItem(String description, LocalDateTime createDate) { + this.description = description; + this.createDate = createDate; + } + + public TodoItem() { + // default no arg constructor + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public LocalDateTime getCreateDate() { + return createDate; + } + + public void setCreateDate(LocalDateTime createDate) { + this.createDate = createDate; + } + + @Override + public String toString() { + return "TodoItem [description=" + description + ", createDate=" + createDate + "]"; + } +} diff --git a/spring-5/src/main/java/com/baeldung/sessionattrs/TodoList.java b/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoList.java similarity index 94% rename from spring-5/src/main/java/com/baeldung/sessionattrs/TodoList.java rename to spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoList.java index cad7811da4..02c05f4282 100644 --- a/spring-5/src/main/java/com/baeldung/sessionattrs/TodoList.java +++ b/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoList.java @@ -1,8 +1,8 @@ -package com.baeldung.sessionattrs; - -import java.util.ArrayDeque; - -@SuppressWarnings("serial") -public class TodoList extends ArrayDeque{ - -} +package com.baeldung.sessionattrs; + +import java.util.ArrayDeque; + +@SuppressWarnings("serial") +public class TodoList extends ArrayDeque{ + +} diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/application.properties b/spring-mvc-forms-thymeleaf/src/main/resources/application.properties new file mode 100644 index 0000000000..ccec014c2b --- /dev/null +++ b/spring-mvc-forms-thymeleaf/src/main/resources/application.properties @@ -0,0 +1,3 @@ +server.port=8081 + +logging.level.root=INFO \ No newline at end of file diff --git a/spring-5/src/main/resources/templates/sessionattrs/index.html b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/index.html similarity index 97% rename from spring-5/src/main/resources/templates/sessionattrs/index.html rename to spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/index.html index 72427cd62b..f9df863e45 100644 --- a/spring-5/src/main/resources/templates/sessionattrs/index.html +++ b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/index.html @@ -1,27 +1,27 @@ - - - - Session Scope in Spring MVC - - - - - - - -
-

-

Session Scope in Spring MVC - Example

-

-
- - + + + + Session Scope in Spring MVC + + + + + + + +
+

+

Session Scope in Spring MVC - Example

+

+
+ + \ No newline at end of file diff --git a/spring-5/src/main/resources/templates/sessionattrs/scopedproxyform.html b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxyform.html similarity index 97% rename from spring-5/src/main/resources/templates/sessionattrs/scopedproxyform.html rename to spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxyform.html index e72651556b..604c60dfbb 100644 --- a/spring-5/src/main/resources/templates/sessionattrs/scopedproxyform.html +++ b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxyform.html @@ -1,27 +1,27 @@ - - - - Session Scope in Spring MVC - - - - - - - -
-

-

Scoped Proxy Example

-

-
-
-
Enter a TODO
-
-
- - -
-
-
- + + + + Session Scope in Spring MVC + + + + + + + +
+

+

Scoped Proxy Example

+

+
+
+
Enter a TODO
+
+
+ + +
+
+
+ \ No newline at end of file diff --git a/spring-5/src/main/resources/templates/sessionattrs/scopedproxytodos.html b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxytodos.html similarity index 96% rename from spring-5/src/main/resources/templates/sessionattrs/scopedproxytodos.html rename to spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxytodos.html index 5493b5cf64..743cd76b5d 100644 --- a/spring-5/src/main/resources/templates/sessionattrs/scopedproxytodos.html +++ b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxytodos.html @@ -1,48 +1,48 @@ - - - - Session Scope in Spring MVC - - - - - - - -
-

-

Scoped Proxy Example

-

-
-
-
-
- Add New -
-
-
-
-
-
TODO List
- - - - - - - - - - - -
DescriptionCreate Date
DescriptionCreate Date
-
-
-
-
- + + + + Session Scope in Spring MVC + + + + + + + +
+

+

Scoped Proxy Example

+

+
+
+
+
+ Add New +
+
+
+
+
+
TODO List
+ + + + + + + + + + + +
DescriptionCreate Date
DescriptionCreate Date
+
+
+
+
+ \ No newline at end of file diff --git a/spring-5/src/main/resources/templates/sessionattrs/sessionattributesform.html b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributesform.html similarity index 97% rename from spring-5/src/main/resources/templates/sessionattrs/sessionattributesform.html rename to spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributesform.html index 28e1d5d2c1..93e052d6b5 100644 --- a/spring-5/src/main/resources/templates/sessionattrs/sessionattributesform.html +++ b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributesform.html @@ -1,27 +1,27 @@ - - - - Session Scope in Spring MVC - - - - - - - -
-

-

Session Attributes Example

-

-
-
-
Enter a TODO
-
-
- - -
-
-
- + + + + Session Scope in Spring MVC + + + + + + + +
+

+

Session Attributes Example

+

+
+
+
Enter a TODO
+
+
+ + +
+
+
+ \ No newline at end of file diff --git a/spring-5/src/main/resources/templates/sessionattrs/sessionattributestodos.html b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributestodos.html similarity index 96% rename from spring-5/src/main/resources/templates/sessionattrs/sessionattributestodos.html rename to spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributestodos.html index 4bae12ffb9..7525604298 100644 --- a/spring-5/src/main/resources/templates/sessionattrs/sessionattributestodos.html +++ b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributestodos.html @@ -1,48 +1,48 @@ - - - - Session Scope in Spring MVC - - - - - - - -
-

-

Session Attributes Example

-

-
-
-
-
- Add New -
-
-
-
-
-
TODO List
- - - - - - - - - - - -
DescriptionCreate Date
DescriptionCreate Date
-
-
-
-
- + + + + Session Scope in Spring MVC + + + + + + + +
+

+

Session Attributes Example

+

+
+
+
+
+ Add New +
+
+
+
+
+
TODO List
+ + + + + + + + + + + +
DescriptionCreate Date
DescriptionCreate Date
+
+
+
+
+ \ No newline at end of file diff --git a/spring-5/src/test/java/com/baeldung/sessionattrs/SessionAttrsApplicationIntegrationTest.java b/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/SessionAttrsApplicationTest.java similarity index 85% rename from spring-5/src/test/java/com/baeldung/sessionattrs/SessionAttrsApplicationIntegrationTest.java rename to spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/SessionAttrsApplicationTest.java index 05e9cdd21e..2fc27841da 100644 --- a/spring-5/src/test/java/com/baeldung/sessionattrs/SessionAttrsApplicationIntegrationTest.java +++ b/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/SessionAttrsApplicationTest.java @@ -7,7 +7,7 @@ import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest -public class SessionAttrsApplicationIntegrationTest { +public class SessionAttrsApplicationTest { @Test public void contextLoads() { diff --git a/spring-5/src/test/java/com/baeldung/sessionattrs/TestConfig.java b/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TestConfig.java similarity index 97% rename from spring-5/src/test/java/com/baeldung/sessionattrs/TestConfig.java rename to spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TestConfig.java index 07d65dd7c2..cf38463c0f 100644 --- a/spring-5/src/test/java/com/baeldung/sessionattrs/TestConfig.java +++ b/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TestConfig.java @@ -1,17 +1,17 @@ -package com.baeldung.sessionattrs; - -import org.springframework.beans.factory.config.CustomScopeConfigurer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.support.SimpleThreadScope; - -@Configuration -public class TestConfig { - - @Bean - public CustomScopeConfigurer customScopeConfigurer() { - CustomScopeConfigurer configurer = new CustomScopeConfigurer(); - configurer.addScope("session", new SimpleThreadScope()); - return configurer; - } -} +package com.baeldung.sessionattrs; + +import org.springframework.beans.factory.config.CustomScopeConfigurer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.SimpleThreadScope; + +@Configuration +public class TestConfig { + + @Bean + public CustomScopeConfigurer customScopeConfigurer() { + CustomScopeConfigurer configurer = new CustomScopeConfigurer(); + configurer.addScope("session", new SimpleThreadScope()); + return configurer; + } +} diff --git a/spring-5/src/test/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxyIntegrationTest.java b/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxyTest.java similarity index 91% rename from spring-5/src/test/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxyIntegrationTest.java rename to spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxyTest.java index 5b2f653f8a..49be948a2a 100644 --- a/spring-5/src/test/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxyIntegrationTest.java +++ b/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxyTest.java @@ -1,68 +1,68 @@ -package com.baeldung.sessionattrs; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.util.StringUtils; -import org.springframework.web.context.WebApplicationContext; - -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -@Import(TestConfig.class) -public class TodoControllerWithScopedProxyIntegrationTest { - - @Autowired - private MockMvc mockMvc; - - @Autowired - private WebApplicationContext wac; - - @Before - public void setup() { - this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac) - .build(); - } - - @Test - public void whenFirstRequest_thenContainsAllCategoriesAndUnintializedTodo() throws Exception { - MvcResult result = mockMvc.perform(get("/scopedproxy/form")) - .andExpect(status().isOk()) - .andExpect(model().attributeExists("todo")) - .andReturn(); - - TodoItem item = (TodoItem) result.getModelAndView().getModel().get("todo"); - assertTrue(StringUtils.isEmpty(item.getDescription())); - } - - @Test - public void whenSubmit_thenSubsequentFormRequestContainsMostRecentTodo() throws Exception { - mockMvc.perform(post("/scopedproxy/form") - .param("description", "newtodo")) - .andExpect(status().is3xxRedirection()) - .andReturn(); - - MvcResult result = mockMvc.perform(get("/scopedproxy/form")) - .andExpect(status().isOk()) - .andExpect(model().attributeExists("todo")) - .andReturn(); - TodoItem item = (TodoItem) result.getModelAndView().getModel().get("todo"); - assertEquals("newtodo", item.getDescription()); - } - -} +package com.baeldung.sessionattrs; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.util.StringUtils; +import org.springframework.web.context.WebApplicationContext; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc +@Import(TestConfig.class) +public class TodoControllerWithScopedProxyTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext wac; + + @Before + public void setup() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac) + .build(); + } + + @Test + public void whenFirstRequest_thenContainsUnintializedTodo() throws Exception { + MvcResult result = mockMvc.perform(get("/scopedproxy/form")) + .andExpect(status().isOk()) + .andExpect(model().attributeExists("todo")) + .andReturn(); + + TodoItem item = (TodoItem) result.getModelAndView().getModel().get("todo"); + assertTrue(StringUtils.isEmpty(item.getDescription())); + } + + @Test + public void whenSubmit_thenSubsequentFormRequestContainsMostRecentTodo() throws Exception { + mockMvc.perform(post("/scopedproxy/form") + .param("description", "newtodo")) + .andExpect(status().is3xxRedirection()) + .andReturn(); + + MvcResult result = mockMvc.perform(get("/scopedproxy/form")) + .andExpect(status().isOk()) + .andExpect(model().attributeExists("todo")) + .andReturn(); + TodoItem item = (TodoItem) result.getModelAndView().getModel().get("todo"); + assertEquals("newtodo", item.getDescription()); + } + +} diff --git a/spring-5/src/test/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributesIntegrationTest.java b/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributesTest.java similarity index 95% rename from spring-5/src/test/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributesIntegrationTest.java rename to spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributesTest.java index c97fc79f29..e41de880d3 100644 --- a/spring-5/src/test/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributesIntegrationTest.java +++ b/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributesTest.java @@ -1,68 +1,68 @@ -package com.baeldung.sessionattrs; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.util.StringUtils; -import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.servlet.FlashMap; - -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -public class TodoControllerWithSessionAttributesIntegrationTest { - - @Autowired - private MockMvc mockMvc; - - @Autowired - private WebApplicationContext wac; - - @Before - public void setup() { - this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac) - .build(); - } - - @Test - public void whenFirstRequest_thenContainsUnintializedTodo() throws Exception { - MvcResult result = mockMvc.perform(get("/sessionattributes/form")) - .andExpect(status().isOk()) - .andExpect(model().attributeExists("todo")) - .andReturn(); - - TodoItem item = (TodoItem) result.getModelAndView().getModel().get("todo"); - assertTrue(StringUtils.isEmpty(item.getDescription())); - } - - @Test - public void whenSubmit_thenSubsequentFormRequestContainsMostRecentTodo() throws Exception { - FlashMap flashMap = mockMvc.perform(post("/sessionattributes/form") - .param("description", "newtodo")) - .andExpect(status().is3xxRedirection()) - .andReturn().getFlashMap(); - - MvcResult result = mockMvc.perform(get("/sessionattributes/form") - .sessionAttrs(flashMap)) - .andExpect(status().isOk()) - .andExpect(model().attributeExists("todo")) - .andReturn(); - TodoItem item = (TodoItem) result.getModelAndView().getModel().get("todo"); - assertEquals("newtodo", item.getDescription()); - } - -} +package com.baeldung.sessionattrs; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.util.StringUtils; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.FlashMap; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc +public class TodoControllerWithSessionAttributesTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext wac; + + @Before + public void setup() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac) + .build(); + } + + @Test + public void whenFirstRequest_thenContainsUnintializedTodo() throws Exception { + MvcResult result = mockMvc.perform(get("/sessionattributes/form")) + .andExpect(status().isOk()) + .andExpect(model().attributeExists("todo")) + .andReturn(); + + TodoItem item = (TodoItem) result.getModelAndView().getModel().get("todo"); + assertTrue(StringUtils.isEmpty(item.getDescription())); + } + + @Test + public void whenSubmit_thenSubsequentFormRequestContainsMostRecentTodo() throws Exception { + FlashMap flashMap = mockMvc.perform(post("/sessionattributes/form") + .param("description", "newtodo")) + .andExpect(status().is3xxRedirection()) + .andReturn().getFlashMap(); + + MvcResult result = mockMvc.perform(get("/sessionattributes/form") + .sessionAttrs(flashMap)) + .andExpect(status().isOk()) + .andExpect(model().attributeExists("todo")) + .andReturn(); + TodoItem item = (TodoItem) result.getModelAndView().getModel().get("todo"); + assertEquals("newtodo", item.getDescription()); + } + +} From af7f39371641ff574c6e3193ad4ded31c831e74f Mon Sep 17 00:00:00 2001 From: Chris Oberle Date: Sat, 10 Mar 2018 07:19:57 -0500 Subject: [PATCH 6/7] update title of html pages --- .../src/main/resources/templates/sessionattrs/index.html | 2 +- .../main/resources/templates/sessionattrs/scopedproxyform.html | 2 +- .../main/resources/templates/sessionattrs/scopedproxytodos.html | 2 +- .../resources/templates/sessionattrs/sessionattributesform.html | 2 +- .../templates/sessionattrs/sessionattributestodos.html | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/index.html b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/index.html index f9df863e45..d0c4c7cd3a 100644 --- a/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/index.html +++ b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/index.html @@ -1,7 +1,7 @@ - Session Scope in Spring MVC + Session Attributes in Spring MVC diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxyform.html b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxyform.html index 604c60dfbb..ebb3e16525 100644 --- a/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxyform.html +++ b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxyform.html @@ -1,7 +1,7 @@ - Session Scope in Spring MVC + Session Attributes in Spring MVC diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxytodos.html b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxytodos.html index 743cd76b5d..f7916b0f8a 100644 --- a/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxytodos.html +++ b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxytodos.html @@ -1,7 +1,7 @@ - Session Scope in Spring MVC + Session Attributes in Spring MVC diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributesform.html b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributesform.html index 93e052d6b5..73233c12f3 100644 --- a/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributesform.html +++ b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributesform.html @@ -1,7 +1,7 @@ - Session Scope in Spring MVC + Session Attributes in Spring MVC diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributestodos.html b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributestodos.html index 7525604298..753ee133e9 100644 --- a/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributestodos.html +++ b/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributestodos.html @@ -1,7 +1,7 @@ - Session Scope in Spring MVC + Session Attributes in Spring MVC From f50d111c5e5d4fbb4e0a85ae8c621d46e0b8403f Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 11 Mar 2018 13:18:35 -0500 Subject: [PATCH 7/7] BAEL-1068 (#3456) * BAEL-1068 - Javadoc example classes * BAEL-1068 - Formatting change for pom.xml * Updated javadoc comments to reflect article example * Added javadoc tags for throws, deprecated, and version and a clause to throw an exception --- .../src/main/java/com/baeldung/javadoc/SuperHero.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core-java/src/main/java/com/baeldung/javadoc/SuperHero.java b/core-java/src/main/java/com/baeldung/javadoc/SuperHero.java index 029a779cdb..561430f66f 100644 --- a/core-java/src/main/java/com/baeldung/javadoc/SuperHero.java +++ b/core-java/src/main/java/com/baeldung/javadoc/SuperHero.java @@ -23,9 +23,15 @@ public class SuperHero extends Person { * @return the amount of health hero has after attack * @see HERO-402 * @since 1.0 + * @deprecated As of version 1.1, use . . . instead + * @version 1.2 + * @throws IllegalArgumentException if incomingDamage is negative */ - public int successfullyAttacked(int incomingDamage, String damageType) { + public int successfullyAttacked(int incomingDamage, String damageType) throws Exception { // do things + if (incomingDamage < 0) { + throw new IllegalArgumentException ("Cannot cause negative damage"); + } return 0; }