├── .gitignore ├── LICENSE ├── README.md ├── pom.xml └── src ├── main ├── java │ └── org │ │ └── springframework │ │ ├── mvc │ │ └── extensions │ │ │ └── ajax │ │ │ └── AjaxUtils.java │ │ └── samples │ │ └── mvc │ │ ├── async │ │ ├── CallableController.java │ │ ├── DeferredResultController.java │ │ ├── JavaBean.java │ │ └── TimeoutCallableProcessingInterceptor.java │ │ ├── config │ │ ├── MvcShowcaseAppInitializer.java │ │ ├── RootConfig.java │ │ └── WebMvcConfig.java │ │ ├── convert │ │ ├── ConvertController.java │ │ ├── JavaBean.java │ │ ├── MaskFormat.java │ │ ├── MaskFormatAnnotationFormatterFactory.java │ │ ├── NestedBean.java │ │ └── SocialSecurityNumber.java │ │ ├── data │ │ ├── JavaBean.java │ │ ├── RequestDataController.java │ │ ├── custom │ │ │ ├── CustomArgumentController.java │ │ │ ├── CustomArgumentResolver.java │ │ │ └── RequestAttribute.java │ │ └── standard │ │ │ └── StandardArgumentsController.java │ │ ├── exceptions │ │ ├── BusinessException.java │ │ ├── ExceptionController.java │ │ └── GlobalExceptionHandler.java │ │ ├── fileupload │ │ └── FileUploadController.java │ │ ├── form │ │ ├── FormBean.java │ │ ├── FormController.java │ │ └── InquiryType.java │ │ ├── mapping │ │ ├── ClasslevelMappingController.java │ │ ├── JavaBean.java │ │ └── MappingController.java │ │ ├── messageconverters │ │ ├── JavaBean.java │ │ └── MessageConvertersController.java │ │ ├── redirect │ │ └── RedirectController.java │ │ ├── response │ │ └── ResponseController.java │ │ ├── simple │ │ ├── SimpleController.java │ │ └── SimpleControllerRevisited.java │ │ ├── validation │ │ ├── JavaBean.java │ │ └── ValidationController.java │ │ └── views │ │ ├── JavaBean.java │ │ └── ViewsController.java ├── resources │ └── log4j2.xml └── webapp │ ├── WEB-INF │ └── views │ │ ├── fileupload.jsp │ │ ├── form.jsp │ │ ├── home.jsp │ │ ├── redirect │ │ └── redirectResults.jsp │ │ └── views │ │ ├── dataBinding.jsp │ │ ├── html.jsp │ │ └── viewName.jsp │ └── resources │ ├── form.css │ ├── jquery │ └── 1.6 │ │ └── jquery.js │ ├── jqueryform │ └── 2.8 │ │ └── jquery.form.js │ ├── jqueryui │ └── 1.8 │ │ ├── jquery.ui.core.js │ │ ├── jquery.ui.tabs.js │ │ ├── jquery.ui.widget.js │ │ └── themes │ │ └── base │ │ ├── images │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png │ │ ├── ui-bg_flat_75_ffffff_40x100.png │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ ├── ui-bg_glass_75_dadada_1x400.png │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png │ │ ├── ui-bg_glass_95_fef1ec_1x400.png │ │ ├── ui-bg_highlight-soft_75_cccccc_1x100.png │ │ ├── ui-icons_222222_256x240.png │ │ ├── ui-icons_2e83ff_256x240.png │ │ ├── ui-icons_454545_256x240.png │ │ ├── ui-icons_888888_256x240.png │ │ └── ui-icons_cd0a0a_256x240.png │ │ ├── jquery.ui.all.css │ │ ├── jquery.ui.base.css │ │ ├── jquery.ui.core.css │ │ ├── jquery.ui.tabs.css │ │ └── jquery.ui.theme.css │ ├── json2.js │ └── messages │ ├── error.png │ ├── info.png │ ├── messages.css │ ├── success.png │ └── warning.png └── test ├── java └── org │ └── springframework │ └── samples │ └── mvc │ ├── AbstractContextControllerTests.java │ ├── async │ ├── CallableControllerTests.java │ └── DeferredResultControllerTests.java │ ├── convert │ └── ConvertControllerTests.java │ ├── data │ ├── CustomArgumentControllerTests.java │ ├── DataControllerTests.java │ └── StandardArgumentsControllerTests.java │ ├── exceptions │ └── ExceptionControllerTests.java │ ├── fileupload │ └── FileUploadControllerTests.java │ ├── form │ └── FormControllerTests.java │ ├── mapping │ └── MappingControllerTests.java │ ├── messageconverters │ └── MessageConvertersControllerTests.java │ ├── redirect │ └── RedirectControllerTests.java │ ├── response │ └── ResponseControllerTests.java │ ├── simple │ ├── SimpleControllerRevisitedTests.java │ └── SimpleControllerTests.java │ ├── validation │ └── ValidationControllerTests.java │ └── views │ └── ViewsControllerTests.java └── resources └── log4j2-test.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | bin 3 | target 4 | .classpath 5 | .project 6 | .settings 7 | src/main/webapp/META-INF 8 | .idea 9 | *.iml 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2015-Present Pivotal Software Inc. 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # spring-mvc-showcase is no longer actively maintained by VMware, Inc. 2 | 3 | Spring MVC Showcase 4 | ------------------- 5 | Demonstrates the capabilities of the Spring MVC web framework through small, simple examples. 6 | After reviewing this showcase, you should have a good understanding of what Spring MVC can do and get a feel for how easy it is to use. 7 | Includes project code along with a supporting slideshow and screen cast. 8 | 9 | In this showcase you'll see the following in action: 10 | 11 | * The simplest possible @Controller 12 | * Mapping Requests 13 | * Obtaining Request Data 14 | * Generating Responses 15 | * Message Converters 16 | * Rendering Views 17 | * Type Conversion 18 | * Validation 19 | * Forms 20 | * File Upload 21 | * Exception Handling 22 | 23 | To get the code: 24 | ------------------- 25 | Clone the repository: 26 | 27 | $ git clone git://github.com/SpringSource/spring-mvc-showcase.git 28 | 29 | If this is your first time using Github, review https://help.github.com to learn the basics. 30 | 31 | To run the application: 32 | ------------------- 33 | From the command line with Maven: 34 | 35 | $ cd spring-mvc-showcase 36 | $ mvn jetty:run 37 | 38 | Access the deployed web application at: http://localhost:8080/spring-mvc-showcase/ 39 | 40 | Note: 41 | ------------------- 42 | 43 | This showcase originated from a [blog post](https://spring.io/blog/2010/07/22/spring-mvc-3-showcase/) and was adapted into a SpringOne presentation called [Mastering MVC 3](https://www.infoq.com/presentations/Mastering-Spring-MVC-3). 44 | 45 | A screen cast showing the showcase in action is [available in QuickTime format](http://s3.springsource.org/MVC/mvc-showcase-screencast.mov). 46 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | org.springframework.samples 6 | spring-mvc-showcase 7 | spring-mvc-showcase 8 | war 9 | 1.0.0-BUILD-SNAPSHOT 10 | 11 | 12 | 1.8 13 | 5.0.4.RELEASE 14 | 1.8.1 15 | 16 | 17 | 18 | 19 | 20 | org.springframework 21 | spring-context 22 | ${org.springframework-version} 23 | 24 | 25 | org.springframework 26 | spring-webmvc 27 | ${org.springframework-version} 28 | 29 | 30 | 31 | 32 | org.springframework.security 33 | spring-security-web 34 | 5.0.0.RELEASE 35 | 36 | 37 | 38 | 39 | org.aspectj 40 | aspectjrt 41 | ${org.aspectj-version} 42 | 43 | 44 | 45 | 46 | org.apache.logging.log4j 47 | log4j-core 48 | LATEST 49 | 50 | 51 | org.apache.logging.log4j 52 | log4j-slf4j-impl 53 | LATEST 54 | 55 | 56 | 57 | 58 | javax.inject 59 | javax.inject 60 | 1 61 | 62 | 63 | 64 | 65 | javax.servlet 66 | javax.servlet-api 67 | 3.1.0 68 | provided 69 | 70 | 71 | javax.servlet.jsp 72 | javax.servlet.jsp-api 73 | 2.3.2-b02 74 | provided 75 | 76 | 77 | javax.servlet 78 | jstl 79 | 1.2 80 | 81 | 82 | 83 | 84 | com.fasterxml.jackson.core 85 | jackson-databind 86 | 2.9.3 87 | 88 | 89 | 90 | 91 | com.rometools 92 | rome 93 | 1.9.0 94 | 95 | 96 | 97 | 98 | javax.validation 99 | validation-api 100 | 2.0.1.Final 101 | 102 | 103 | org.hibernate.validator 104 | hibernate-validator 105 | 6.0.7.Final 106 | 107 | 108 | javax.el 109 | javax.el-api 110 | 3.0.1-b04 111 | 112 | 113 | org.glassfish 114 | javax.el 115 | 3.0.1-b08 116 | 117 | 118 | 119 | 120 | joda-time 121 | joda-time 122 | 2.9.9 123 | 124 | 125 | 126 | 127 | commons-fileupload 128 | commons-fileupload 129 | 1.3.3 130 | 131 | 132 | commons-io 133 | commons-io 134 | 2.5 135 | 136 | 137 | 138 | 139 | 140 | org.springframework 141 | spring-test 142 | ${org.springframework-version} 143 | test 144 | 145 | 146 | junit 147 | junit 148 | 4.12 149 | test 150 | 151 | 152 | org.xmlunit 153 | xmlunit-matchers 154 | 2.5.1 155 | test 156 | 157 | 158 | com.jayway.jsonpath 159 | json-path 160 | 2.4.0 161 | test 162 | 163 | 164 | org.hamcrest 165 | hamcrest-library 166 | 1.3 167 | test 168 | 169 | 170 | 171 | 172 | ${project.artifactId} 173 | 174 | 175 | org.apache.maven.plugins 176 | maven-compiler-plugin 177 | 3.7.0 178 | 179 | ${java-version} 180 | ${java-version} 181 | 182 | 183 | 184 | org.apache.maven.plugins 185 | maven-war-plugin 186 | 187 | false 188 | 189 | 190 | 191 | org.apache.maven.plugins 192 | maven-surefire-plugin 193 | 2.20.1 194 | 195 | 196 | **/*Tests.java 197 | 198 | 199 | **/Abstract*.java 200 | 201 | junit:junit 202 | -Xmx512m 203 | 204 | 205 | 206 | org.apache.maven.plugins 207 | maven-dependency-plugin 208 | 209 | 210 | install 211 | install 212 | 213 | sources 214 | 215 | 216 | 217 | 218 | 219 | org.codehaus.mojo 220 | aspectj-maven-plugin 221 | 1.11 222 | 223 | 224 | org.aspectj 225 | aspectjrt 226 | ${org.aspectj-version} 227 | 228 | 229 | org.aspectj 230 | aspectjtools 231 | ${org.aspectj-version} 232 | 233 | 234 | 235 | 236 | 237 | compile 238 | test-compile 239 | 240 | 241 | 242 | 243 | true 244 | ${java-version} 245 | ${java-version} 246 | ${java-version} 247 | 248 | 249 | 250 | org.eclipse.jetty 251 | jetty-maven-plugin 252 | 9.4.8.v20171121 253 | 254 | 255 | /${project.artifactId} 256 | 257 | 258 | 259 | 260 | 261 | 262 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/mvc/extensions/ajax/AjaxUtils.java: -------------------------------------------------------------------------------- 1 | package org.springframework.mvc.extensions.ajax; 2 | 3 | import org.springframework.web.context.request.WebRequest; 4 | 5 | public class AjaxUtils { 6 | 7 | public static boolean isAjaxRequest(WebRequest webRequest) { 8 | String requestedWith = webRequest.getHeader("X-Requested-With"); 9 | return requestedWith != null ? "XMLHttpRequest".equals(requestedWith) : false; 10 | } 11 | 12 | public static boolean isAjaxUploadRequest(WebRequest webRequest) { 13 | return webRequest.getParameter("ajaxUpload") != null; 14 | } 15 | 16 | private AjaxUtils() {} 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/async/CallableController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.async; 2 | 3 | import java.util.concurrent.Callable; 4 | 5 | import org.springframework.stereotype.Controller; 6 | import org.springframework.ui.Model; 7 | import org.springframework.web.bind.annotation.ExceptionHandler; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestParam; 11 | import org.springframework.web.bind.annotation.ResponseBody; 12 | import org.springframework.web.context.request.async.WebAsyncTask; 13 | 14 | @Controller 15 | @RequestMapping("/async/callable") 16 | public class CallableController { 17 | 18 | 19 | @GetMapping("/response-body") 20 | public @ResponseBody Callable callable() { 21 | 22 | return new Callable() { 23 | @Override 24 | public String call() throws Exception { 25 | Thread.sleep(2000); 26 | return "Callable result"; 27 | } 28 | }; 29 | } 30 | 31 | @GetMapping("/view") 32 | public Callable callableWithView(final Model model) { 33 | return () -> { 34 | Thread.sleep(2000); 35 | model.addAttribute("foo", "bar"); 36 | model.addAttribute("fruit", "apple"); 37 | return "views/html"; 38 | }; 39 | } 40 | 41 | @GetMapping("/exception") 42 | public @ResponseBody Callable callableWithException( 43 | final @RequestParam(required=false, defaultValue="true") boolean handled) { 44 | 45 | return () -> { 46 | Thread.sleep(2000); 47 | if (handled) { 48 | // see handleException method further below 49 | throw new IllegalStateException("Callable error"); 50 | } 51 | else { 52 | throw new IllegalArgumentException("Callable error"); 53 | } 54 | }; 55 | } 56 | 57 | @GetMapping("/custom-timeout-handling") 58 | public @ResponseBody WebAsyncTask callableWithCustomTimeoutHandling() { 59 | Callable callable = () -> { 60 | Thread.sleep(2000); 61 | return "Callable result"; 62 | }; 63 | return new WebAsyncTask(1000, callable); 64 | } 65 | 66 | @ExceptionHandler 67 | @ResponseBody 68 | public String handleException(IllegalStateException ex) { 69 | return "Handled exception: " + ex.getMessage(); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/async/DeferredResultController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.async; 2 | 3 | import java.util.Queue; 4 | import java.util.concurrent.ConcurrentLinkedQueue; 5 | 6 | import org.springframework.scheduling.annotation.Scheduled; 7 | import org.springframework.stereotype.Controller; 8 | import org.springframework.web.bind.annotation.ExceptionHandler; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseBody; 12 | import org.springframework.web.context.request.async.DeferredResult; 13 | import org.springframework.web.servlet.ModelAndView; 14 | 15 | @Controller 16 | @RequestMapping("/async") 17 | public class DeferredResultController { 18 | 19 | private final Queue> responseBodyQueue = new ConcurrentLinkedQueue<>(); 20 | 21 | private final Queue> mavQueue = new ConcurrentLinkedQueue<>(); 22 | 23 | private final Queue> exceptionQueue = new ConcurrentLinkedQueue<>(); 24 | 25 | 26 | @GetMapping("/deferred-result/response-body") 27 | public @ResponseBody DeferredResult deferredResult() { 28 | DeferredResult result = new DeferredResult<>(); 29 | this.responseBodyQueue.add(result); 30 | return result; 31 | } 32 | 33 | @GetMapping("/deferred-result/model-and-view") 34 | public DeferredResult deferredResultWithView() { 35 | DeferredResult result = new DeferredResult<>(); 36 | this.mavQueue.add(result); 37 | return result; 38 | } 39 | 40 | @GetMapping("/deferred-result/exception") 41 | public @ResponseBody DeferredResult deferredResultWithException() { 42 | DeferredResult result = new DeferredResult<>(); 43 | this.exceptionQueue.add(result); 44 | return result; 45 | } 46 | 47 | @GetMapping("/deferred-result/timeout-value") 48 | public @ResponseBody DeferredResult deferredResultWithTimeoutValue() { 49 | 50 | // Provide a default result in case of timeout and override the timeout value 51 | // set in src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml 52 | 53 | return new DeferredResult<>(1000L, "Deferred result after timeout"); 54 | } 55 | 56 | @Scheduled(fixedRate=2000) 57 | public void processQueues() { 58 | for (DeferredResult result : this.responseBodyQueue) { 59 | result.setResult("Deferred result"); 60 | this.responseBodyQueue.remove(result); 61 | } 62 | for (DeferredResult result : this.exceptionQueue) { 63 | result.setErrorResult(new IllegalStateException("DeferredResult error")); 64 | this.exceptionQueue.remove(result); 65 | } 66 | for (DeferredResult result : this.mavQueue) { 67 | result.setResult(new ModelAndView("views/html", "javaBean", new JavaBean("bar", "apple"))); 68 | this.mavQueue.remove(result); 69 | } 70 | } 71 | 72 | @ExceptionHandler 73 | @ResponseBody 74 | public String handleException(IllegalStateException ex) { 75 | return "Handled exception: " + ex.getMessage(); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/async/JavaBean.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.async; 2 | 3 | public class JavaBean { 4 | 5 | private String foo; 6 | 7 | private String fruit; 8 | 9 | public JavaBean(String foo, String fruit) { 10 | this.foo = foo; 11 | this.fruit = fruit; 12 | } 13 | 14 | public String getFoo() { 15 | return foo; 16 | } 17 | 18 | public void setFoo(String foo) { 19 | this.foo = foo; 20 | } 21 | 22 | public String getFruit() { 23 | return fruit; 24 | } 25 | 26 | public void setFruit(String fruit) { 27 | this.fruit = fruit; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/async/TimeoutCallableProcessingInterceptor.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.async; 2 | 3 | import java.util.concurrent.Callable; 4 | 5 | import org.springframework.web.context.request.NativeWebRequest; 6 | import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter; 7 | 8 | public class TimeoutCallableProcessingInterceptor extends CallableProcessingInterceptorAdapter { 9 | 10 | @Override 11 | public Object handleTimeout(NativeWebRequest request, Callable task) { 12 | throw new IllegalStateException("[" + task.getClass().getName() + "] timed out"); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/config/MvcShowcaseAppInitializer.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.config; 2 | 3 | import javax.servlet.Filter; 4 | 5 | import org.springframework.web.filter.DelegatingFilterProxy; 6 | import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; 7 | 8 | /** 9 | * Initialize the Servlet container. This class is detected by the Servlet 10 | * container on startup. 11 | */ 12 | public class MvcShowcaseAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{ 13 | 14 | @Override 15 | protected Class[] getRootConfigClasses() { 16 | return new Class[] { RootConfig.class }; 17 | } 18 | 19 | @Override 20 | protected Class[] getServletConfigClasses() { 21 | return new Class[] { WebMvcConfig.class }; 22 | } 23 | 24 | @Override 25 | protected String[] getServletMappings() { 26 | return new String[] { "/" }; 27 | } 28 | 29 | @Override 30 | protected Filter[] getServletFilters() { 31 | return new Filter[] { new DelegatingFilterProxy("csrfFilter") }; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/config/RootConfig.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.web.csrf.CsrfFilter; 6 | import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository; 7 | import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor; 8 | import org.springframework.web.servlet.support.RequestDataValueProcessor; 9 | 10 | // Root Context: defines shared resources visible to all other web components 11 | 12 | @Configuration 13 | public class RootConfig { 14 | 15 | // CSRF protection. Here we only include the CsrfFilter instead of all of Spring Security. 16 | // See https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#csrf 17 | // for more information on Spring Security's CSRF protection 18 | 19 | @Bean 20 | public CsrfFilter csrfFilter() { 21 | return new CsrfFilter(new HttpSessionCsrfTokenRepository()); 22 | } 23 | 24 | // Provides automatic CSRF token inclusion when using Spring MVC Form tags or Thymeleaf. 25 | // See http://localhost:8080/#forms and form.jsp for examples 26 | 27 | @Bean 28 | public RequestDataValueProcessor requestDataValueProcessor() { 29 | return new CsrfRequestDataValueProcessor(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/config/WebMvcConfig.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.config; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.ComponentScan; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.format.FormatterRegistry; 9 | import org.springframework.samples.mvc.async.TimeoutCallableProcessingInterceptor; 10 | import org.springframework.samples.mvc.convert.MaskFormatAnnotationFormatterFactory; 11 | import org.springframework.samples.mvc.data.custom.CustomArgumentResolver; 12 | import org.springframework.scheduling.annotation.EnableScheduling; 13 | import org.springframework.web.method.support.HandlerMethodArgumentResolver; 14 | import org.springframework.web.multipart.MultipartResolver; 15 | import org.springframework.web.multipart.commons.CommonsMultipartResolver; 16 | import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer; 17 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 18 | import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; 19 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 20 | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; 21 | import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; 22 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 23 | import org.springframework.web.util.UrlPathHelper; 24 | 25 | // DispatcherServlet context: defines Spring MVC infrastructure 26 | // and web application components 27 | 28 | @Configuration 29 | @ComponentScan(basePackages = "org.springframework.samples.mvc") 30 | @EnableWebMvc 31 | @EnableScheduling 32 | public class WebMvcConfig implements WebMvcConfigurer { 33 | 34 | @Override 35 | public void addFormatters(FormatterRegistry registry) { 36 | registry.addFormatterForFieldAnnotation(new MaskFormatAnnotationFormatterFactory()); 37 | } 38 | 39 | @Override 40 | public void addArgumentResolvers(List resolvers) { 41 | resolvers.add(new CustomArgumentResolver()); 42 | } 43 | 44 | // Handle HTTP GET requests for /resources/** by efficiently serving 45 | // static resources under ${webappRoot}/resources/ 46 | 47 | @Override 48 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 49 | registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); 50 | } 51 | 52 | @Override 53 | public void addViewControllers(ViewControllerRegistry registry) { 54 | registry.addViewController("/").setViewName("home"); 55 | } 56 | 57 | @Override 58 | public void configureViewResolvers(ViewResolverRegistry registry) { 59 | registry.jsp("/WEB-INF/views/", ".jsp"); 60 | } 61 | 62 | @Override 63 | public void configurePathMatch(PathMatchConfigurer configurer) { 64 | UrlPathHelper pathHelper = new UrlPathHelper(); 65 | pathHelper.setRemoveSemicolonContent(false); // For @MatrixVariable's 66 | configurer.setUrlPathHelper(pathHelper); 67 | } 68 | 69 | @Override 70 | public void configureAsyncSupport(AsyncSupportConfigurer configurer) { 71 | configurer.setDefaultTimeout(3000); 72 | configurer.registerCallableInterceptors(new TimeoutCallableProcessingInterceptor()); 73 | } 74 | 75 | @Bean 76 | public MultipartResolver multipartResolver() { 77 | return new CommonsMultipartResolver(); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/convert/ConvertController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.convert; 2 | 3 | import java.util.Collection; 4 | import java.util.Date; 5 | 6 | import org.springframework.format.annotation.DateTimeFormat; 7 | import org.springframework.format.annotation.DateTimeFormat.ISO; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.PathVariable; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RequestParam; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | @RestController 15 | @RequestMapping("/convert") 16 | public class ConvertController { 17 | 18 | @GetMapping("primitive") 19 | public String primitive(@RequestParam Integer value) { 20 | return "Converted primitive " + value; 21 | } 22 | 23 | // requires Joda-Time on the classpath 24 | @GetMapping("date/{value}") 25 | public String date(@PathVariable @DateTimeFormat(iso=ISO.DATE) Date value) { 26 | return "Converted date " + value; 27 | } 28 | 29 | @GetMapping("collection") 30 | public String collection(@RequestParam Collection values) { 31 | return "Converted collection " + values; 32 | } 33 | 34 | @GetMapping("formattedCollection") 35 | public String formattedCollection(@RequestParam @DateTimeFormat(iso=ISO.DATE) Collection values) { 36 | return "Converted formatted collection " + values; 37 | } 38 | 39 | @GetMapping("bean") 40 | public String bean(JavaBean bean) { 41 | return "Converted " + bean; 42 | } 43 | 44 | @GetMapping("value") 45 | public String valueObject(@RequestParam SocialSecurityNumber value) { 46 | return "Converted value object " + value; 47 | } 48 | 49 | @GetMapping("custom") 50 | public String customConverter(@RequestParam @MaskFormat("###-##-####") String value) { 51 | return "Converted '" + value + "' with a custom converter"; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/convert/JavaBean.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.convert; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import org.springframework.format.annotation.DateTimeFormat; 8 | import org.springframework.format.annotation.DateTimeFormat.ISO; 9 | 10 | public class JavaBean { 11 | 12 | private Integer primitive; 13 | 14 | @DateTimeFormat(iso=ISO.DATE) 15 | private Date date; 16 | 17 | @MaskFormat("(###) ###-####") 18 | private String masked; 19 | 20 | // list will auto-grow as its dereferenced e.g. list[0]=value 21 | private List list; 22 | 23 | // annotation type conversion rule will be applied to each list element 24 | @DateTimeFormat(iso=ISO.DATE) 25 | private List formattedList; 26 | 27 | // map will auto-grow as its dereferenced e.g. map[key]=value 28 | private Map map; 29 | 30 | // nested will be set when it is referenced e.g. nested.foo=value 31 | private NestedBean nested; 32 | 33 | public Integer getPrimitive() { 34 | return primitive; 35 | } 36 | 37 | public void setPrimitive(Integer primitive) { 38 | this.primitive = primitive; 39 | } 40 | 41 | public Date getDate() { 42 | return date; 43 | } 44 | 45 | public void setDate(Date date) { 46 | this.date = date; 47 | } 48 | 49 | public String getMasked() { 50 | return masked; 51 | } 52 | 53 | public void setMasked(String masked) { 54 | this.masked = masked; 55 | } 56 | 57 | public List getList() { 58 | return list; 59 | } 60 | 61 | public void setList(List list) { 62 | this.list = list; 63 | } 64 | 65 | public List getFormattedList() { 66 | return formattedList; 67 | } 68 | 69 | public void setFormattedList(List formattedList) { 70 | this.formattedList = formattedList; 71 | } 72 | 73 | public Map getMap() { 74 | return map; 75 | } 76 | 77 | public void setMap(Map map) { 78 | this.map = map; 79 | } 80 | 81 | public NestedBean getNested() { 82 | return nested; 83 | } 84 | 85 | public void setNested(NestedBean nested) { 86 | this.nested = nested; 87 | } 88 | 89 | public String toString() { 90 | StringBuilder sb = new StringBuilder(); 91 | sb.append("JavaBean"); 92 | if (primitive != null) { 93 | sb.append(" primitive=").append(primitive); 94 | } 95 | if (date != null) { 96 | sb.append(" date=").append(date); 97 | } 98 | if (masked != null) { 99 | sb.append(" masked=").append(masked); 100 | } 101 | if (list != null) { 102 | sb.append(" list=").append(list); 103 | } 104 | if (formattedList != null) { 105 | sb.append(" formattedList=").append(formattedList); 106 | } 107 | if (map != null) { 108 | sb.append(" map=").append(map); 109 | } 110 | if (nested != null) { 111 | sb.append(" nested=").append(nested); 112 | } 113 | return sb.toString(); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/convert/MaskFormat.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.convert; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | @Target(value={ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface MaskFormat { 13 | String value(); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/convert/MaskFormatAnnotationFormatterFactory.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.convert; 2 | 3 | import java.text.ParseException; 4 | import java.util.HashSet; 5 | import java.util.Locale; 6 | import java.util.Set; 7 | 8 | import org.springframework.format.AnnotationFormatterFactory; 9 | import org.springframework.format.Formatter; 10 | import org.springframework.format.Parser; 11 | import org.springframework.format.Printer; 12 | 13 | public class MaskFormatAnnotationFormatterFactory implements AnnotationFormatterFactory { 14 | 15 | public Set> getFieldTypes() { 16 | Set> fieldTypes = new HashSet>(1, 1); 17 | fieldTypes.add(String.class); 18 | return fieldTypes; 19 | } 20 | 21 | public Parser getParser(MaskFormat annotation, Class fieldType) { 22 | return new MaskFormatter(annotation.value()); 23 | } 24 | 25 | public Printer getPrinter(MaskFormat annotation, Class fieldType) { 26 | return new MaskFormatter(annotation.value()); 27 | } 28 | 29 | private static class MaskFormatter implements Formatter { 30 | 31 | private javax.swing.text.MaskFormatter delegate; 32 | 33 | public MaskFormatter(String mask) { 34 | try { 35 | this.delegate = new javax.swing.text.MaskFormatter(mask); 36 | this.delegate.setValueContainsLiteralCharacters(false); 37 | } catch (ParseException e) { 38 | throw new IllegalStateException("Mask could not be parsed " + mask, e); 39 | } 40 | } 41 | 42 | public String print(String object, Locale locale) { 43 | try { 44 | return delegate.valueToString(object); 45 | } catch (ParseException e) { 46 | throw new IllegalArgumentException("Unable to print using mask " + delegate.getMask(), e); 47 | } 48 | } 49 | 50 | public String parse(String text, Locale locale) throws ParseException { 51 | return (String) delegate.stringToValue(text); 52 | } 53 | 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/convert/NestedBean.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.convert; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | public class NestedBean { 7 | 8 | private String foo; 9 | 10 | private List list; 11 | 12 | private Map map; 13 | 14 | public String getFoo() { 15 | return foo; 16 | } 17 | 18 | public void setFoo(String foo) { 19 | this.foo = foo; 20 | } 21 | 22 | public List getList() { 23 | return list; 24 | } 25 | 26 | public void setList(List list) { 27 | this.list = list; 28 | } 29 | 30 | public Map getMap() { 31 | return map; 32 | } 33 | 34 | public void setMap(Map map) { 35 | this.map = map; 36 | } 37 | 38 | public String toString() { 39 | StringBuilder sb = new StringBuilder(); 40 | sb.append("NestedBean"); 41 | if (foo != null) { 42 | sb.append(" foo=").append(foo); 43 | } 44 | if (list != null) { 45 | sb.append(" list=").append(list); 46 | } 47 | if (map != null) { 48 | sb.append(" map=").append(map); 49 | } 50 | return sb.toString(); 51 | } 52 | } -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/convert/SocialSecurityNumber.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.convert; 2 | 3 | public final class SocialSecurityNumber { 4 | 5 | private final String value; 6 | 7 | public SocialSecurityNumber(String value) { 8 | this.value = value; 9 | } 10 | 11 | @MaskFormat("###-##-####") 12 | public String getValue() { 13 | return value; 14 | } 15 | 16 | public static SocialSecurityNumber valueOf(@MaskFormat("###-##-####") String value) { 17 | return new SocialSecurityNumber(value); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/data/JavaBean.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.data; 2 | 3 | public class JavaBean { 4 | 5 | private String param1; 6 | 7 | private String param2; 8 | 9 | private String param3; 10 | 11 | public String getParam1() { 12 | return param1; 13 | } 14 | 15 | public void setParam1(String param1) { 16 | this.param1 = param1; 17 | } 18 | 19 | public String getParam2() { 20 | return param2; 21 | } 22 | 23 | public void setParam2(String param2) { 24 | this.param2 = param2; 25 | } 26 | 27 | public String getParam3() { 28 | return param3; 29 | } 30 | 31 | public void setParam3(String param3) { 32 | this.param3 = param3; 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/data/RequestDataController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.data; 2 | 3 | import org.springframework.http.HttpEntity; 4 | import org.springframework.web.bind.annotation.CookieValue; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.MatrixVariable; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestHeader; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestParam; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | @RestController 16 | @RequestMapping("/data") 17 | public class RequestDataController { 18 | 19 | @GetMapping("param") 20 | public String withParam(@RequestParam String foo) { 21 | return "Obtained 'foo' query parameter value '" + foo + "'"; 22 | } 23 | 24 | @GetMapping("group") 25 | public String withParamGroup(JavaBean bean) { 26 | return "Obtained parameter group " + bean; 27 | } 28 | 29 | @GetMapping("path/{var}") 30 | public String withPathVariable(@PathVariable String var) { 31 | return "Obtained 'var' path variable value '" + var + "'"; 32 | } 33 | 34 | @GetMapping("{path}/simple") 35 | public String withMatrixVariable(@PathVariable String path, @MatrixVariable String foo) { 36 | return "Obtained matrix variable 'foo=" + foo + "' from path segment '" + path + "'"; 37 | } 38 | 39 | @GetMapping("{path1}/{path2}") 40 | public String withMatrixVariablesMultiple ( 41 | @PathVariable String path1, @MatrixVariable(name="foo", pathVar="path1") String foo1, 42 | @PathVariable String path2, @MatrixVariable(name="foo", pathVar="path2") String foo2) { 43 | 44 | return "Obtained matrix variable foo=" + foo1 + " from path segment '" + path1 45 | + "' and variable 'foo=" + foo2 + " from path segment '" + path2 + "'"; 46 | } 47 | 48 | @GetMapping("header") 49 | public String withHeader(@RequestHeader String Accept) { 50 | return "Obtained 'Accept' header '" + Accept + "'"; 51 | } 52 | 53 | @GetMapping("cookie") 54 | public String withCookie(@CookieValue String openid_provider) { 55 | return "Obtained 'openid_provider' cookie '" + openid_provider + "'"; 56 | } 57 | 58 | @PostMapping("body") 59 | public String withBody(@RequestBody String body) { 60 | return "Posted request body '" + body + "'"; 61 | } 62 | 63 | @PostMapping("entity") 64 | public String withEntity(HttpEntity entity) { 65 | return "Posted request body '" + entity.getBody() + "'; headers = " + entity.getHeaders(); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/data/custom/CustomArgumentController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.data.custom; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.ModelAttribute; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | public class CustomArgumentController { 11 | 12 | @ModelAttribute 13 | void beforeInvokingHandlerMethod(HttpServletRequest request) { 14 | request.setAttribute("foo", "bar"); 15 | } 16 | 17 | @GetMapping("/data/custom") 18 | public String custom(@RequestAttribute("foo") String foo) { 19 | return "Got 'foo' request attribute value '" + foo + "'"; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/data/custom/CustomArgumentResolver.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.data.custom; 2 | 3 | import org.springframework.core.MethodParameter; 4 | import org.springframework.web.bind.support.WebDataBinderFactory; 5 | import org.springframework.web.context.request.NativeWebRequest; 6 | import org.springframework.web.context.request.WebRequest; 7 | import org.springframework.web.method.support.HandlerMethodArgumentResolver; 8 | import org.springframework.web.method.support.ModelAndViewContainer; 9 | 10 | public class CustomArgumentResolver implements HandlerMethodArgumentResolver { 11 | 12 | public boolean supportsParameter(MethodParameter parameter) { 13 | return parameter.getParameterAnnotation(RequestAttribute.class) != null; 14 | } 15 | 16 | public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, 17 | NativeWebRequest webRequest, WebDataBinderFactory binderFactory) 18 | throws Exception { 19 | 20 | RequestAttribute attr = parameter.getParameterAnnotation(RequestAttribute.class); 21 | return webRequest.getAttribute(attr.value(), WebRequest.SCOPE_REQUEST); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/data/custom/RequestAttribute.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.data.custom; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | @Target(ElementType.PARAMETER) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface RequestAttribute { 13 | String value(); 14 | } -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/data/standard/StandardArgumentsController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.data.standard; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.io.Reader; 7 | import java.io.Writer; 8 | import java.security.Principal; 9 | import java.util.Locale; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import javax.servlet.http.HttpSession; 13 | 14 | import org.springframework.util.FileCopyUtils; 15 | import org.springframework.web.bind.annotation.GetMapping; 16 | import org.springframework.web.bind.annotation.PostMapping; 17 | import org.springframework.web.bind.annotation.RestController; 18 | 19 | @RestController 20 | public class StandardArgumentsController { 21 | 22 | // request related 23 | 24 | @GetMapping("/data/standard/request") 25 | public String standardRequestArgs(HttpServletRequest request, Principal user, Locale locale) { 26 | StringBuilder buffer = new StringBuilder(); 27 | buffer.append("request = ").append(request).append(", "); 28 | buffer.append("userPrincipal = ").append(user).append(", "); 29 | buffer.append("requestLocale = ").append(locale); 30 | return buffer.toString(); 31 | } 32 | 33 | @PostMapping("/data/standard/request/reader") 34 | public String requestReader(Reader requestBodyReader) throws IOException { 35 | return "Read char request body = " + FileCopyUtils.copyToString(requestBodyReader); 36 | } 37 | 38 | @PostMapping("/data/standard/request/is") 39 | public String requestReader(InputStream requestBodyIs) throws IOException { 40 | return "Read binary request body = " + new String(FileCopyUtils.copyToByteArray(requestBodyIs)); 41 | } 42 | 43 | // response related 44 | 45 | @GetMapping("/data/standard/response") 46 | public String response(HttpServletResponse response) { 47 | return "response = " + response; 48 | } 49 | 50 | @GetMapping("/data/standard/response/writer") 51 | public void availableStandardResponseArguments(Writer responseWriter) throws IOException { 52 | responseWriter.write("Wrote char response using Writer"); 53 | } 54 | 55 | @GetMapping("/data/standard/response/os") 56 | public void availableStandardResponseArguments(OutputStream os) throws IOException { 57 | os.write("Wrote binary response using OutputStream".getBytes()); 58 | } 59 | 60 | // HttpSession 61 | 62 | @GetMapping("/data/standard/session") 63 | public String session(HttpSession session) { 64 | StringBuilder buffer = new StringBuilder(); 65 | buffer.append("session=").append(session); 66 | return buffer.toString(); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/exceptions/BusinessException.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.exceptions; 2 | 3 | @SuppressWarnings("serial") 4 | public class BusinessException extends Exception { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/exceptions/ExceptionController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.exceptions; 2 | 3 | import org.springframework.web.bind.annotation.ExceptionHandler; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | public class ExceptionController { 9 | 10 | @GetMapping("/exception") 11 | public String exception() { 12 | throw new IllegalStateException("Sorry!"); 13 | } 14 | 15 | @GetMapping("/global-exception") 16 | public String businessException() throws BusinessException { 17 | throw new BusinessException(); 18 | } 19 | 20 | @ExceptionHandler 21 | public String handle(IllegalStateException e) { 22 | return "IllegalStateException handled!"; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/exceptions/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.exceptions; 2 | 3 | import org.springframework.web.bind.annotation.ExceptionHandler; 4 | import org.springframework.web.bind.annotation.RestControllerAdvice; 5 | 6 | @RestControllerAdvice 7 | public class GlobalExceptionHandler { 8 | 9 | @ExceptionHandler 10 | public String handleBusinessException(BusinessException ex) { 11 | return "Handled BusinessException"; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/fileupload/FileUploadController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.fileupload; 2 | 3 | import org.springframework.mvc.extensions.ajax.AjaxUtils; 4 | import org.springframework.stereotype.Controller; 5 | import org.springframework.ui.Model; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.ModelAttribute; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestParam; 11 | import org.springframework.web.context.request.WebRequest; 12 | import org.springframework.web.multipart.MultipartFile; 13 | 14 | @Controller 15 | @RequestMapping("/fileupload") 16 | public class FileUploadController { 17 | 18 | @ModelAttribute 19 | public void ajaxAttribute(WebRequest request, Model model) { 20 | model.addAttribute("ajaxRequest", AjaxUtils.isAjaxRequest(request)); 21 | } 22 | 23 | @GetMapping 24 | public void fileUploadForm() { 25 | } 26 | 27 | @PostMapping 28 | public void processUpload(@RequestParam MultipartFile file, Model model) { 29 | model.addAttribute("message", "File '" + file.getOriginalFilename() + "' uploaded successfully"); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/form/FormBean.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.form; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.Date; 5 | import java.util.Map; 6 | 7 | import javax.validation.constraints.Min; 8 | import javax.validation.constraints.Past; 9 | 10 | import org.hibernate.validator.constraints.NotEmpty; 11 | import org.springframework.format.annotation.DateTimeFormat; 12 | import org.springframework.format.annotation.NumberFormat; 13 | import org.springframework.format.annotation.DateTimeFormat.ISO; 14 | import org.springframework.format.annotation.NumberFormat.Style; 15 | import org.springframework.samples.mvc.convert.MaskFormat; 16 | 17 | public class FormBean { 18 | 19 | @NotEmpty 20 | private String name; 21 | 22 | @Min(21) 23 | private int age; 24 | 25 | @DateTimeFormat(iso=ISO.DATE) 26 | @Past 27 | private Date birthDate; 28 | 29 | @MaskFormat("(###) ###-####") 30 | private String phone; 31 | 32 | @NumberFormat(pattern="$###,###.00") 33 | private BigDecimal currency; 34 | 35 | @NumberFormat(style=Style.PERCENT) 36 | private BigDecimal percent; 37 | 38 | private InquiryType inquiry; 39 | 40 | private String inquiryDetails; 41 | 42 | private boolean subscribeNewsletter; 43 | 44 | private Map additionalInfo; 45 | 46 | public String getName() { 47 | return name; 48 | } 49 | 50 | public void setName(String name) { 51 | this.name = name; 52 | } 53 | 54 | public int getAge() { 55 | return age; 56 | } 57 | 58 | public void setAge(int age) { 59 | this.age = age; 60 | } 61 | 62 | public Date getBirthDate() { 63 | return birthDate; 64 | } 65 | 66 | public void setBirthDate(Date birthDate) { 67 | this.birthDate = birthDate; 68 | } 69 | 70 | public String getPhone() { 71 | return phone; 72 | } 73 | 74 | public void setPhone(String phone) { 75 | this.phone = phone; 76 | } 77 | 78 | public BigDecimal getCurrency() { 79 | return currency; 80 | } 81 | 82 | public void setCurrency(BigDecimal currency) { 83 | this.currency = currency; 84 | } 85 | 86 | public BigDecimal getPercent() { 87 | return percent; 88 | } 89 | 90 | public void setPercent(BigDecimal percent) { 91 | this.percent = percent; 92 | } 93 | 94 | public InquiryType getInquiry() { 95 | return inquiry; 96 | } 97 | 98 | public void setInquiry(InquiryType inquiry) { 99 | this.inquiry = inquiry; 100 | } 101 | 102 | public String getInquiryDetails() { 103 | return inquiryDetails; 104 | } 105 | 106 | public void setInquiryDetails(String inquiryDetails) { 107 | this.inquiryDetails = inquiryDetails; 108 | } 109 | 110 | public boolean isSubscribeNewsletter() { 111 | return subscribeNewsletter; 112 | } 113 | 114 | public void setSubscribeNewsletter(boolean subscribeNewsletter) { 115 | this.subscribeNewsletter = subscribeNewsletter; 116 | } 117 | 118 | public Map getAdditionalInfo() { 119 | return additionalInfo; 120 | } 121 | 122 | public void setAdditionalInfo(Map additionalInfo) { 123 | this.additionalInfo = additionalInfo; 124 | } 125 | 126 | public String toString() { 127 | StringBuilder sb = new StringBuilder(); 128 | sb.append("properties name="); 129 | if (name != null) { 130 | sb.append("'").append(name).append("', "); 131 | } else { 132 | sb.append(name).append(", "); 133 | } 134 | sb.append("age=").append(age).append(", "); 135 | sb.append("birthDate=").append(birthDate).append(", "); 136 | sb.append("phone="); 137 | if (phone != null) { 138 | sb.append("'").append(phone).append("', "); 139 | } else { 140 | sb.append(phone).append(", "); 141 | } 142 | sb.append("currency=").append(currency).append(", "); 143 | sb.append("percent=").append(percent).append(", "); 144 | sb.append("inquiry=").append(inquiry).append(", "); 145 | sb.append("inquiryDetails="); 146 | if (inquiryDetails != null) { 147 | sb.append("'").append(inquiryDetails).append("', "); 148 | } else { 149 | sb.append(inquiryDetails).append(", "); 150 | } 151 | sb.append("subscribeNewsletter=").append(subscribeNewsletter).append(", "); 152 | sb.append("additionalInfo=").append(additionalInfo); 153 | return sb.toString(); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/form/FormController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.form; 2 | 3 | import javax.validation.Valid; 4 | 5 | import org.springframework.mvc.extensions.ajax.AjaxUtils; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.ui.Model; 8 | import org.springframework.validation.BindingResult; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.ModelAttribute; 11 | import org.springframework.web.bind.annotation.PostMapping; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.SessionAttributes; 14 | import org.springframework.web.context.request.WebRequest; 15 | import org.springframework.web.servlet.mvc.support.RedirectAttributes; 16 | 17 | @Controller 18 | @RequestMapping("/form") 19 | @SessionAttributes("formBean") 20 | public class FormController { 21 | 22 | // Invoked on every request 23 | 24 | @ModelAttribute 25 | public void ajaxAttribute(WebRequest request, Model model) { 26 | model.addAttribute("ajaxRequest", AjaxUtils.isAjaxRequest(request)); 27 | } 28 | 29 | // Invoked initially to create the "form" attribute 30 | // Once created the "form" attribute comes from the HTTP session (see @SessionAttributes) 31 | 32 | @ModelAttribute("formBean") 33 | public FormBean createFormBean() { 34 | return new FormBean(); 35 | } 36 | 37 | @GetMapping 38 | public void form() { 39 | } 40 | 41 | @PostMapping 42 | public String processSubmit(@Valid FormBean formBean, BindingResult result, 43 | @ModelAttribute("ajaxRequest") boolean ajaxRequest, 44 | Model model, RedirectAttributes redirectAttrs) { 45 | if (result.hasErrors()) { 46 | return null; 47 | } 48 | // Typically you would save to a db and clear the "form" attribute from the session 49 | // via SessionStatus.setCompleted(). For the demo we leave it in the session. 50 | String message = "Form submitted successfully. Bound " + formBean; 51 | // Success response handling 52 | if (ajaxRequest) { 53 | // prepare model for rendering success message in this request 54 | model.addAttribute("message", message); 55 | return null; 56 | } else { 57 | // store a success message for rendering on the next request after redirect 58 | // redirect back to the form to render the success message along with newly bound values 59 | redirectAttrs.addFlashAttribute("message", message); 60 | return "redirect:/form"; 61 | } 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/form/InquiryType.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.form; 2 | 3 | public enum InquiryType { 4 | comment, feedback, suggestion; 5 | } -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/mapping/ClasslevelMappingController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.mapping; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.PostMapping; 7 | import org.springframework.web.bind.annotation.RequestBody; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | @RestController 12 | @RequestMapping("/class-mapping/*") 13 | public class ClasslevelMappingController { 14 | 15 | @GetMapping("/path") 16 | public String byPath() { 17 | return "Mapped by path!"; 18 | } 19 | 20 | @GetMapping("/path/*") 21 | public String byPathPattern(HttpServletRequest request) { 22 | return "Mapped by path pattern ('" + request.getRequestURI() + "')"; 23 | } 24 | 25 | @GetMapping("/method") 26 | public String byMethod() { 27 | return "Mapped by path + method"; 28 | } 29 | 30 | @GetMapping(path="/parameter", params="foo") 31 | public String byParameter() { 32 | return "Mapped by path + method + presence of query parameter!"; 33 | } 34 | 35 | @GetMapping(path="/parameter", params="!foo") 36 | public String byParameterNegation() { 37 | return "Mapped by path + method + not presence of query!"; 38 | } 39 | 40 | @GetMapping(path="/header", headers="FooHeader=foo") 41 | public String byHeader() { 42 | return "Mapped by path + method + presence of header!"; 43 | } 44 | 45 | @GetMapping(path="/notheader", headers="!FooHeader") 46 | public String byHeaderNegation() { 47 | return "Mapped by path + method + absence of header!"; 48 | } 49 | 50 | 51 | @PostMapping(path="/consumes", consumes="application/json") 52 | public String byConsumes(@RequestBody JavaBean javaBean) { 53 | return "Mapped by path + method + consumable media type (javaBean '" + javaBean + "')"; 54 | } 55 | 56 | @GetMapping(path="/produces", produces="application/json") 57 | public JavaBean byProduces() { 58 | return new JavaBean(); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/mapping/JavaBean.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.mapping; 2 | 3 | import javax.xml.bind.annotation.XmlRootElement; 4 | 5 | @XmlRootElement 6 | public class JavaBean { 7 | 8 | private String foo = "bar"; 9 | 10 | private String fruit = "apple"; 11 | 12 | public String getFoo() { 13 | return foo; 14 | } 15 | 16 | public void setFoo(String foo) { 17 | this.foo = foo; 18 | } 19 | 20 | public String getFruit() { 21 | return fruit; 22 | } 23 | 24 | public void setFruit(String fruit) { 25 | this.fruit = fruit; 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | return "JavaBean {foo=[" + foo + "], fruit=[" + fruit + "]}"; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/mapping/MappingController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.mapping; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | import org.springframework.http.MediaType; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PostMapping; 8 | import org.springframework.web.bind.annotation.RequestBody; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | @RestController 12 | public class MappingController { 13 | 14 | @GetMapping("/mapping/path") 15 | public String byPath() { 16 | return "Mapped by path!"; 17 | } 18 | 19 | @GetMapping("/mapping/path/*") 20 | public String byPathPattern(HttpServletRequest request) { 21 | return "Mapped by path pattern ('" + request.getRequestURI() + "')"; 22 | } 23 | 24 | @GetMapping("/mapping/method") 25 | public String byMethod() { 26 | return "Mapped by path + method"; 27 | } 28 | 29 | @GetMapping(path="/mapping/parameter", params="foo") 30 | public String byParameter() { 31 | return "Mapped by path + method + presence of query parameter!"; 32 | } 33 | 34 | @GetMapping(path="/mapping/parameter", params="!foo") 35 | public String byParameterNegation() { 36 | return "Mapped by path + method + not presence of query parameter!"; 37 | } 38 | 39 | @GetMapping(path="/mapping/header", headers="FooHeader=foo") 40 | public String byHeader() { 41 | return "Mapped by path + method + presence of header!"; 42 | } 43 | 44 | @GetMapping(path="/mapping/header", headers="!FooHeader") 45 | public String byHeaderNegation() { 46 | return "Mapped by path + method + absence of header!"; 47 | } 48 | 49 | @PostMapping(path="/mapping/consumes", consumes=MediaType.APPLICATION_JSON_VALUE) 50 | public String byConsumes(@RequestBody JavaBean javaBean) { 51 | return "Mapped by path + method + consumable media type (javaBean '" + javaBean + "')"; 52 | } 53 | 54 | @GetMapping(path="/mapping/produces", produces=MediaType.APPLICATION_JSON_VALUE) 55 | public JavaBean byProducesJson() { 56 | return new JavaBean(); 57 | } 58 | 59 | @GetMapping(path="/mapping/produces", produces=MediaType.APPLICATION_XML_VALUE) 60 | public JavaBean byProducesXml() { 61 | return new JavaBean(); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/messageconverters/JavaBean.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.messageconverters; 2 | 3 | import javax.validation.constraints.NotNull; 4 | import javax.xml.bind.annotation.XmlRootElement; 5 | 6 | @XmlRootElement 7 | public class JavaBean { 8 | 9 | @NotNull 10 | private String foo; 11 | 12 | @NotNull 13 | private String fruit; 14 | 15 | public JavaBean() { 16 | } 17 | 18 | public JavaBean(String foo, String fruit) { 19 | this.foo = foo; 20 | this.fruit = fruit; 21 | } 22 | 23 | public String getFoo() { 24 | return foo; 25 | } 26 | 27 | public void setFoo(String foo) { 28 | this.foo = foo; 29 | } 30 | 31 | public String getFruit() { 32 | return fruit; 33 | } 34 | 35 | public void setFruit(String fruit) { 36 | this.fruit = fruit; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "JavaBean {foo=[" + foo + "], fruit=[" + fruit + "]}"; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/messageconverters/MessageConvertersController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.messageconverters; 2 | 3 | import javax.validation.Valid; 4 | 5 | import com.rometools.rome.feed.atom.Feed; 6 | import com.rometools.rome.feed.rss.Channel; 7 | 8 | import org.springframework.util.LinkedMultiValueMap; 9 | import org.springframework.util.MultiValueMap; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.ModelAttribute; 12 | import org.springframework.web.bind.annotation.PostMapping; 13 | import org.springframework.web.bind.annotation.RequestBody; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.ResponseBody; 16 | import org.springframework.web.bind.annotation.RestController; 17 | 18 | @RestController 19 | @RequestMapping("/messageconverters") 20 | public class MessageConvertersController { 21 | 22 | // StringHttpMessageConverter 23 | 24 | @PostMapping("/string") 25 | public String readString(@RequestBody String string) { 26 | return "Read string '" + string + "'"; 27 | } 28 | 29 | @GetMapping("/string") 30 | public String writeString() { 31 | return "Wrote a string"; 32 | } 33 | 34 | // Form encoded data (application/x-www-form-urlencoded) 35 | 36 | @PostMapping("/form") 37 | public String readForm(@ModelAttribute JavaBean bean) { 38 | return "Read x-www-form-urlencoded: " + bean; 39 | } 40 | 41 | @GetMapping("/form") 42 | public MultiValueMap writeForm() { 43 | MultiValueMap map = new LinkedMultiValueMap(); 44 | map.add("foo", "bar"); 45 | map.add("fruit", "apple"); 46 | return map; 47 | } 48 | 49 | // Jaxb2RootElementHttpMessageConverter (requires JAXB2 on the classpath - useful for serving clients that expect to work with XML) 50 | 51 | @PostMapping("/xml") 52 | public String readXml(@RequestBody JavaBean bean) { 53 | return "Read from XML: " + bean; 54 | } 55 | 56 | @GetMapping("/xml") 57 | public JavaBean writeXml() { 58 | return new JavaBean("bar", "apple"); 59 | } 60 | 61 | // MappingJacksonHttpMessageConverter (requires Jackson on the classpath - particularly useful for serving JavaScript clients that expect to work with JSON) 62 | 63 | @PostMapping("/json") 64 | public String readJson(@Valid @RequestBody JavaBean bean) { 65 | return "Read from JSON: " + bean; 66 | } 67 | 68 | @GetMapping("/json") 69 | public JavaBean writeJson() { 70 | return new JavaBean("bar", "apple"); 71 | } 72 | 73 | // AtomFeedHttpMessageConverter (requires Rome on the classpath - useful for serving Atom feeds) 74 | 75 | @PostMapping("/atom") 76 | public String readFeed(@RequestBody Feed feed) { 77 | return "Read " + feed.getTitle(); 78 | } 79 | 80 | @GetMapping("/atom") 81 | public Feed writeFeed() { 82 | Feed feed = new Feed(); 83 | feed.setFeedType("atom_1.0"); 84 | feed.setTitle("My Atom feed"); 85 | return feed; 86 | } 87 | 88 | // RssChannelHttpMessageConverter (requires Rome on the classpath - useful for serving RSS feeds) 89 | 90 | @PostMapping("/rss") 91 | public String readChannel(@RequestBody Channel channel) { 92 | return "Read " + channel.getTitle(); 93 | } 94 | 95 | @GetMapping("/rss") 96 | public Channel writeChannel() { 97 | Channel channel = new Channel(); 98 | channel.setFeedType("rss_2.0"); 99 | channel.setTitle("My RSS feed"); 100 | channel.setDescription("Description"); 101 | channel.setLink("http://localhost:8080/mvc-showcase/rss"); 102 | return channel; 103 | } 104 | 105 | } -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/redirect/RedirectController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.redirect; 2 | 3 | import javax.inject.Inject; 4 | 5 | import org.joda.time.LocalDate; 6 | 7 | import org.springframework.core.convert.ConversionService; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.PathVariable; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestParam; 13 | import org.springframework.web.servlet.mvc.support.RedirectAttributes; 14 | import org.springframework.web.util.UriComponents; 15 | import org.springframework.web.util.UriComponentsBuilder; 16 | 17 | @Controller 18 | @RequestMapping("/redirect") 19 | public class RedirectController { 20 | 21 | private final ConversionService conversionService; 22 | 23 | @Inject 24 | public RedirectController(ConversionService conversionService) { 25 | this.conversionService = conversionService; 26 | } 27 | 28 | @GetMapping("/uriTemplate") 29 | public String uriTemplate(RedirectAttributes redirectAttrs) { 30 | redirectAttrs.addAttribute("account", "a123"); // Used as URI template variable 31 | redirectAttrs.addAttribute("date", new LocalDate(2011, 12, 31)); // Appended as a query parameter 32 | return "redirect:/redirect/{account}"; 33 | } 34 | 35 | @GetMapping("/uriComponentsBuilder") 36 | public String uriComponentsBuilder() { 37 | String date = this.conversionService.convert(new LocalDate(2011, 12, 31), String.class); 38 | UriComponents redirectUri = UriComponentsBuilder.fromPath("/redirect/{account}").queryParam("date", date) 39 | .build().expand("a123").encode(); 40 | return "redirect:" + redirectUri.toUriString(); 41 | } 42 | 43 | @GetMapping("/{account}") 44 | public String show(@PathVariable String account, @RequestParam(required=false) LocalDate date) { 45 | return "redirect/redirectResults"; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/response/ResponseController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.response; 2 | 3 | import org.springframework.http.HttpHeaders; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.http.MediaType; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RequestMethod; 10 | import org.springframework.web.bind.annotation.RestController; 11 | 12 | @RestController 13 | @RequestMapping(value="/response", method=RequestMethod.GET) 14 | public class ResponseController { 15 | 16 | @GetMapping("/annotation") 17 | public String responseBody() { 18 | return "The String ResponseBody"; 19 | } 20 | 21 | @GetMapping("/charset/accept") 22 | public String responseAcceptHeaderCharset() { 23 | return "\u3053\u3093\u306b\u3061\u306f\u4e16\u754c\uff01 (\"Hello world!\" in Japanese)"; 24 | } 25 | 26 | @GetMapping(value="/charset/produce", produces="text/plain;charset=UTF-8") 27 | public String responseProducesConditionCharset() { 28 | return "\u3053\u3093\u306b\u3061\u306f\u4e16\u754c\uff01 (\"Hello world!\" in Japanese)"; 29 | } 30 | 31 | @GetMapping("/entity/status") 32 | public ResponseEntity responseEntityStatusCode() { 33 | return new ResponseEntity("The String ResponseBody with custom status code (403 Forbidden)", 34 | HttpStatus.FORBIDDEN); 35 | } 36 | 37 | @GetMapping("/entity/headers") 38 | public ResponseEntity responseEntityCustomHeaders() { 39 | HttpHeaders headers = new HttpHeaders(); 40 | headers.setContentType(MediaType.TEXT_PLAIN); 41 | return new ResponseEntity("The String ResponseBody with custom header Content-Type=text/plain", 42 | headers, HttpStatus.OK); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/simple/SimpleController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.simple; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | @RestController 7 | public class SimpleController { 8 | 9 | @GetMapping("/simple") 10 | public String simple() { 11 | return "Hello world!"; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/simple/SimpleControllerRevisited.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.simple; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | @RestController 7 | public class SimpleControllerRevisited { 8 | 9 | @GetMapping(path="/simple/revisited", headers="Accept=text/plain") 10 | public String simple() { 11 | return "Hello world revisited!"; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/validation/JavaBean.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.validation; 2 | 3 | import java.util.Date; 4 | 5 | import javax.validation.constraints.Future; 6 | import javax.validation.constraints.Max; 7 | import javax.validation.constraints.NotNull; 8 | 9 | import org.springframework.format.annotation.DateTimeFormat; 10 | import org.springframework.format.annotation.DateTimeFormat.ISO; 11 | 12 | public class JavaBean { 13 | 14 | @NotNull 15 | @Max(5) 16 | private Integer number; 17 | 18 | @NotNull 19 | @Future 20 | @DateTimeFormat(iso=ISO.DATE) 21 | private Date date; 22 | 23 | public Integer getNumber() { 24 | return number; 25 | } 26 | 27 | public void setNumber(Integer number) { 28 | this.number = number; 29 | } 30 | 31 | public Date getDate() { 32 | return date; 33 | } 34 | 35 | public void setDate(Date date) { 36 | this.date = date; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/validation/ValidationController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.validation; 2 | 3 | import javax.validation.Valid; 4 | 5 | import org.springframework.stereotype.Controller; 6 | import org.springframework.validation.BindingResult; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | @RestController 11 | public class ValidationController { 12 | 13 | // enforcement of constraints on the JavaBean arg require a JSR-303 provider on the classpath 14 | 15 | @GetMapping("/validate") 16 | public String validate(@Valid JavaBean bean, BindingResult result) { 17 | if (result.hasErrors()) { 18 | return "Object has validation errors"; 19 | } else { 20 | return "No errors"; 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/views/JavaBean.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.views; 2 | 3 | import javax.validation.constraints.NotNull; 4 | 5 | public class JavaBean { 6 | 7 | @NotNull 8 | private String foo; 9 | 10 | @NotNull 11 | private String fruit; 12 | 13 | public String getFoo() { 14 | return foo; 15 | } 16 | 17 | public void setFoo(String foo) { 18 | this.foo = foo; 19 | } 20 | 21 | public String getFruit() { 22 | return fruit; 23 | } 24 | 25 | public void setFruit(String fruit) { 26 | this.fruit = fruit; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/samples/mvc/views/ViewsController.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.views; 2 | 3 | import javax.validation.Valid; 4 | 5 | import org.springframework.stereotype.Controller; 6 | import org.springframework.ui.Model; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | 11 | @Controller 12 | @RequestMapping("/views/*") 13 | public class ViewsController { 14 | 15 | @GetMapping("html") 16 | public String prepare(Model model) { 17 | model.addAttribute("foo", "bar"); 18 | model.addAttribute("fruit", "apple"); 19 | return "views/html"; 20 | } 21 | 22 | @GetMapping("/viewName") 23 | public void usingRequestToViewNameTranslator(Model model) { 24 | model.addAttribute("foo", "bar"); 25 | model.addAttribute("fruit", "apple"); 26 | } 27 | 28 | @GetMapping("pathVariables/{foo}/{fruit}") 29 | public String pathVars(@PathVariable String foo, @PathVariable String fruit) { 30 | // No need to add @PathVariables "foo" and "fruit" to the model 31 | // They will be merged in the model before rendering 32 | return "views/html"; 33 | } 34 | 35 | @GetMapping("dataBinding/{foo}/{fruit}") 36 | public String dataBinding(@Valid JavaBean javaBean, Model model) { 37 | // JavaBean "foo" and "fruit" properties populated from URI variables 38 | return "views/dataBinding"; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/fileupload.jsp: -------------------------------------------------------------------------------- 1 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 2 | 3 | 4 | 5 | fileupload | mvc-showcase 6 | " rel="stylesheet" type="text/css" /> 7 | 8 | 9 | 10 | 11 | 12 |
13 |

File Upload

14 |

15 | See the org.springframework.samples.mvc.fileupload package for the @Controller code 16 |

17 | 21 | 22 |
23 |
24 |

Form

25 | 26 |
${message}
27 |
28 |
29 | 30 | 31 |

32 |
33 | 42 |
43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/form.jsp: -------------------------------------------------------------------------------- 1 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 2 | <%@ taglib uri="http://www.springframework.org/tags" prefix="s" %> 3 | <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> 4 | <%@ page session="false" %> 5 | 6 | 7 | 8 | forms | mvc-showcase 9 | " rel="stylesheet" type="text/css" /> 10 | 11 | 12 | 13 | 14 |
15 |

Forms

16 |

17 | See the org.springframework.samples.mvc.form package for the @Controller code 18 |

19 | 20 |
21 |

Form

22 | 23 |
24 |
25 | 26 | 27 |
Form has errors
28 |
29 |
30 |
31 |
32 | Personal Info 33 | 34 | Name 35 | 36 | 37 | 38 | 39 | Age 40 | 41 | 42 | 43 | 44 | Birth Date (in form yyyy-mm-dd) 45 | 46 | 47 | 48 | 49 | Phone (in form (###) ###-####) 50 | 51 | 52 | 53 | 54 | Currency (in form $#.##) 55 | 56 | 57 | 58 | 59 | Percentage (in form ##%) 60 | 61 | 62 | 63 |
64 | 65 |
66 | Inquiry 67 | 68 | Type (select one) 69 | 70 | 71 | Comment 72 | Feedback 73 | Suggestion 74 | 75 | 76 | 77 | Details 78 | 79 | 80 |
81 | 82 |
83 | Request Additional Info 84 | 85 | 86 |
87 | 88 |
89 | Subscribe to Newsletter? 90 | 91 | 92 |
93 | 94 |

95 |
96 | 107 |
108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/redirect/redirectResults.jsp: -------------------------------------------------------------------------------- 1 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 2 | <%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %> 3 | <%@ page session="false" %> 4 | 5 | 6 | Redirect Results 7 | " rel="stylesheet" type="text/css" /> 8 | 9 | 10 |
11 |

Path variable 'account': ${account}

12 |

Query param 'date': ${param.date}

13 |
14 | 15 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/views/dataBinding.jsp: -------------------------------------------------------------------------------- 1 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 2 | <%@ page session="false" %> 3 | 4 | 5 | Data Binding with URI Template Variables 6 | " rel="stylesheet" type="text/css" /> 7 | 8 | 9 |
10 |

javaBean.foo: ${javaBean.foo}

11 |

javaBean.fruit: ${javaBean.fruit}

12 |
13 | 14 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/views/html.jsp: -------------------------------------------------------------------------------- 1 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 2 | <%@ page session="false" %> 3 | 4 | 5 | My HTML View 6 | " rel="stylesheet" type="text/css" /> 7 | 8 | 9 |
10 |

foo: "${foo}"

11 |

fruit: "${fruit}"

12 |
13 | 14 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/views/views/viewName.jsp: -------------------------------------------------------------------------------- 1 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 2 | <%@ page session="false" %> 3 | 4 | 5 | My HTML View 6 | " rel="stylesheet" type="text/css" /> 7 | 8 | 9 |
10 |

foo: "${foo}"

11 |

fruit: "${fruit}"

12 |
13 | 14 | -------------------------------------------------------------------------------- /src/main/webapp/resources/form.css: -------------------------------------------------------------------------------- 1 | @import url("messages/messages.css"); 2 | 3 | /* CLEAN FORM 4 | /////////////////////////////*/ 5 | 6 | /* General */ 7 | 8 | .cleanform { 9 | font-size:1em; 10 | width:40em; 11 | color:#1b1b1b; 12 | text-align:left; 13 | margin:1em auto 14 | } 15 | 16 | /* Elements */ 17 | 18 | .cleanform label,.cleanform legend { 19 | padding:0; 20 | margin:0.3em 0 21 | } 22 | 23 | .cleanform fieldset { 24 | padding:0.7em; 25 | border:1px solid #ddd; 26 | margin:0 0 0.5em 0 27 | } 28 | 29 | .cleanform label { 30 | font-weight:bold 31 | } 32 | 33 | .cleanform fieldset input { 34 | width:70%; 35 | line-height:1.5em; 36 | padding:0.15em 37 | } 38 | 39 | .cleanform .radio input, 40 | .cleanform .checkbox input { 41 | width:auto; 42 | border:none; 43 | margin:0 1.5em 0 0 44 | } 45 | 46 | .cleanform input, .cleanform textarea, .cleanform select { 47 | display:block; 48 | margin-bottom:1em; 49 | font-size:1em; 50 | border:1px solid #bbb; 51 | padding:0.15em; 52 | margin-right:1em 53 | } 54 | 55 | .cleanform .radio label, .cleanform .radio input, 56 | .cleanform .checkbox label, .cleanform .checkbox input { 57 | display:inline; 58 | margin:0 1.5em 0 0 59 | } 60 | 61 | .cleanform .radio input, .cleanform .checkbox input { 62 | margin:0 0.3em 0 0 63 | } 64 | 65 | .cleanform .multiple label{ 66 | float:left; 67 | width:29%; 68 | overflow:hidden; 69 | padding-left:1px 70 | } 71 | 72 | .cleanform .multiple input { 73 | cursor:pointer 74 | } 75 | 76 | 77 | /* information */ 78 | 79 | .cleanform .formInfo { 80 | margin-bottom:1em; 81 | padding-bottom:0.5em; 82 | border-bottom:0.1em solid #ddd 83 | } 84 | 85 | .cleanform .formInfo h2 { 86 | color:#00889e; 87 | font-weight:bold; 88 | font-size:1.2em; 89 | margin-bottom:1em 90 | } 91 | 92 | .cleanform .formInfo p{ 93 | text-align:justify 94 | } 95 | 96 | .cleanform .required { 97 | color:#ff3838; 98 | font-weight:bold; 99 | font-size:0.8em 100 | } -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/jquery.ui.core.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery UI 1.8.13 3 | * 4 | * Copyright 2011, AUTHORS.txt (https://jqueryui.com/about) 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * https://jquery.org/license 7 | * 8 | * https://docs.jquery.com/UI 9 | */ 10 | (function( $, undefined ) { 11 | 12 | // prevent duplicate loading 13 | // this is only a problem because we proxy existing functions 14 | // and we don't want to double proxy them 15 | $.ui = $.ui || {}; 16 | if ( $.ui.version ) { 17 | return; 18 | } 19 | 20 | $.extend( $.ui, { 21 | version: "1.8.13", 22 | 23 | keyCode: { 24 | ALT: 18, 25 | BACKSPACE: 8, 26 | CAPS_LOCK: 20, 27 | COMMA: 188, 28 | COMMAND: 91, 29 | COMMAND_LEFT: 91, // COMMAND 30 | COMMAND_RIGHT: 93, 31 | CONTROL: 17, 32 | DELETE: 46, 33 | DOWN: 40, 34 | END: 35, 35 | ENTER: 13, 36 | ESCAPE: 27, 37 | HOME: 36, 38 | INSERT: 45, 39 | LEFT: 37, 40 | MENU: 93, // COMMAND_RIGHT 41 | NUMPAD_ADD: 107, 42 | NUMPAD_DECIMAL: 110, 43 | NUMPAD_DIVIDE: 111, 44 | NUMPAD_ENTER: 108, 45 | NUMPAD_MULTIPLY: 106, 46 | NUMPAD_SUBTRACT: 109, 47 | PAGE_DOWN: 34, 48 | PAGE_UP: 33, 49 | PERIOD: 190, 50 | RIGHT: 39, 51 | SHIFT: 16, 52 | SPACE: 32, 53 | TAB: 9, 54 | UP: 38, 55 | WINDOWS: 91 // COMMAND 56 | } 57 | }); 58 | 59 | // plugins 60 | $.fn.extend({ 61 | _focus: $.fn.focus, 62 | focus: function( delay, fn ) { 63 | return typeof delay === "number" ? 64 | this.each(function() { 65 | var elem = this; 66 | setTimeout(function() { 67 | $( elem ).focus(); 68 | if ( fn ) { 69 | fn.call( elem ); 70 | } 71 | }, delay ); 72 | }) : 73 | this._focus.apply( this, arguments ); 74 | }, 75 | 76 | scrollParent: function() { 77 | var scrollParent; 78 | if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) { 79 | scrollParent = this.parents().filter(function() { 80 | return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); 81 | }).eq(0); 82 | } else { 83 | scrollParent = this.parents().filter(function() { 84 | return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); 85 | }).eq(0); 86 | } 87 | 88 | return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent; 89 | }, 90 | 91 | zIndex: function( zIndex ) { 92 | if ( zIndex !== undefined ) { 93 | return this.css( "zIndex", zIndex ); 94 | } 95 | 96 | if ( this.length ) { 97 | var elem = $( this[ 0 ] ), position, value; 98 | while ( elem.length && elem[ 0 ] !== document ) { 99 | // Ignore z-index if position is set to a value where z-index is ignored by the browser 100 | // This makes behavior of this function consistent across browsers 101 | // WebKit always returns auto if the element is positioned 102 | position = elem.css( "position" ); 103 | if ( position === "absolute" || position === "relative" || position === "fixed" ) { 104 | // IE returns 0 when zIndex is not specified 105 | // other browsers return a string 106 | // we ignore the case of nested elements with an explicit value of 0 107 | //
108 | value = parseInt( elem.css( "zIndex" ), 10 ); 109 | if ( !isNaN( value ) && value !== 0 ) { 110 | return value; 111 | } 112 | } 113 | elem = elem.parent(); 114 | } 115 | } 116 | 117 | return 0; 118 | }, 119 | 120 | disableSelection: function() { 121 | return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + 122 | ".ui-disableSelection", function( event ) { 123 | event.preventDefault(); 124 | }); 125 | }, 126 | 127 | enableSelection: function() { 128 | return this.unbind( ".ui-disableSelection" ); 129 | } 130 | }); 131 | 132 | $.each( [ "Width", "Height" ], function( i, name ) { 133 | var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], 134 | type = name.toLowerCase(), 135 | orig = { 136 | innerWidth: $.fn.innerWidth, 137 | innerHeight: $.fn.innerHeight, 138 | outerWidth: $.fn.outerWidth, 139 | outerHeight: $.fn.outerHeight 140 | }; 141 | 142 | function reduce( elem, size, border, margin ) { 143 | $.each( side, function() { 144 | size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0; 145 | if ( border ) { 146 | size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0; 147 | } 148 | if ( margin ) { 149 | size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0; 150 | } 151 | }); 152 | return size; 153 | } 154 | 155 | $.fn[ "inner" + name ] = function( size ) { 156 | if ( size === undefined ) { 157 | return orig[ "inner" + name ].call( this ); 158 | } 159 | 160 | return this.each(function() { 161 | $( this ).css( type, reduce( this, size ) + "px" ); 162 | }); 163 | }; 164 | 165 | $.fn[ "outer" + name] = function( size, margin ) { 166 | if ( typeof size !== "number" ) { 167 | return orig[ "outer" + name ].call( this, size ); 168 | } 169 | 170 | return this.each(function() { 171 | $( this).css( type, reduce( this, size, true, margin ) + "px" ); 172 | }); 173 | }; 174 | }); 175 | 176 | // selectors 177 | function focusable( element, isTabIndexNotNaN ) { 178 | var nodeName = element.nodeName.toLowerCase(); 179 | if ( "area" === nodeName ) { 180 | var map = element.parentNode, 181 | mapName = map.name, 182 | img; 183 | if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { 184 | return false; 185 | } 186 | img = $( "img[usemap=#" + mapName + "]" )[0]; 187 | return !!img && visible( img ); 188 | } 189 | return ( /input|select|textarea|button|object/.test( nodeName ) 190 | ? !element.disabled 191 | : "a" == nodeName 192 | ? element.href || isTabIndexNotNaN 193 | : isTabIndexNotNaN) 194 | // the element and all of its ancestors must be visible 195 | && visible( element ); 196 | } 197 | 198 | function visible( element ) { 199 | return !$( element ).parents().andSelf().filter(function() { 200 | return $.curCSS( this, "visibility" ) === "hidden" || 201 | $.expr.filters.hidden( this ); 202 | }).length; 203 | } 204 | 205 | $.extend( $.expr[ ":" ], { 206 | data: function( elem, i, match ) { 207 | return !!$.data( elem, match[ 3 ] ); 208 | }, 209 | 210 | focusable: function( element ) { 211 | return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); 212 | }, 213 | 214 | tabbable: function( element ) { 215 | var tabIndex = $.attr( element, "tabindex" ), 216 | isTabIndexNaN = isNaN( tabIndex ); 217 | return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); 218 | } 219 | }); 220 | 221 | // support 222 | $(function() { 223 | var body = document.body, 224 | div = body.appendChild( div = document.createElement( "div" ) ); 225 | 226 | $.extend( div.style, { 227 | minHeight: "100px", 228 | height: "auto", 229 | padding: 0, 230 | borderWidth: 0 231 | }); 232 | 233 | $.support.minHeight = div.offsetHeight === 100; 234 | $.support.selectstart = "onselectstart" in div; 235 | 236 | // set display to none to avoid a layout bug in IE 237 | // https://dev.jquery.com/ticket/4014 238 | body.removeChild( div ).style.display = "none"; 239 | }); 240 | 241 | 242 | 243 | 244 | 245 | // deprecated 246 | $.extend( $.ui, { 247 | // $.ui.plugin is deprecated. Use the proxy pattern instead. 248 | plugin: { 249 | add: function( module, option, set ) { 250 | var proto = $.ui[ module ].prototype; 251 | for ( var i in set ) { 252 | proto.plugins[ i ] = proto.plugins[ i ] || []; 253 | proto.plugins[ i ].push( [ option, set[ i ] ] ); 254 | } 255 | }, 256 | call: function( instance, name, args ) { 257 | var set = instance.plugins[ name ]; 258 | if ( !set || !instance.element[ 0 ].parentNode ) { 259 | return; 260 | } 261 | 262 | for ( var i = 0; i < set.length; i++ ) { 263 | if ( instance.options[ set[ i ][ 0 ] ] ) { 264 | set[ i ][ 1 ].apply( instance.element, args ); 265 | } 266 | } 267 | } 268 | }, 269 | 270 | // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains() 271 | contains: function( a, b ) { 272 | return document.compareDocumentPosition ? 273 | a.compareDocumentPosition( b ) & 16 : 274 | a !== b && a.contains( b ); 275 | }, 276 | 277 | // only used by resizable 278 | hasScroll: function( el, a ) { 279 | 280 | //If overflow is hidden, the element might have extra content, but the user wants to hide it 281 | if ( $( el ).css( "overflow" ) === "hidden") { 282 | return false; 283 | } 284 | 285 | var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", 286 | has = false; 287 | 288 | if ( el[ scroll ] > 0 ) { 289 | return true; 290 | } 291 | 292 | // TODO: determine which cases actually cause this to happen 293 | // if the element doesn't have the scroll set, see if it's possible to 294 | // set the scroll 295 | el[ scroll ] = 1; 296 | has = ( el[ scroll ] > 0 ); 297 | el[ scroll ] = 0; 298 | return has; 299 | }, 300 | 301 | // these are odd functions, fix the API or move into individual plugins 302 | isOverAxis: function( x, reference, size ) { 303 | //Determines when x coordinate is over "b" element axis 304 | return ( x > reference ) && ( x < ( reference + size ) ); 305 | }, 306 | isOver: function( y, x, top, left, height, width ) { 307 | //Determines when x, y coordinates is over "b" element 308 | return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width ); 309 | } 310 | }); 311 | 312 | })( jQuery ); 313 | -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/jquery.ui.widget.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery UI Widget 1.8.13 3 | * 4 | * Copyright 2011, AUTHORS.txt (https://jqueryui.com/about) 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * https://jquery.org/license 7 | * 8 | * https://docs.jquery.com/UI/Widget 9 | */ 10 | (function( $, undefined ) { 11 | 12 | // jQuery 1.4+ 13 | if ( $.cleanData ) { 14 | var _cleanData = $.cleanData; 15 | $.cleanData = function( elems ) { 16 | for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { 17 | $( elem ).triggerHandler( "remove" ); 18 | } 19 | _cleanData( elems ); 20 | }; 21 | } else { 22 | var _remove = $.fn.remove; 23 | $.fn.remove = function( selector, keepData ) { 24 | return this.each(function() { 25 | if ( !keepData ) { 26 | if ( !selector || $.filter( selector, [ this ] ).length ) { 27 | $( "*", this ).add( [ this ] ).each(function() { 28 | $( this ).triggerHandler( "remove" ); 29 | }); 30 | } 31 | } 32 | return _remove.call( $(this), selector, keepData ); 33 | }); 34 | }; 35 | } 36 | 37 | $.widget = function( name, base, prototype ) { 38 | var namespace = name.split( "." )[ 0 ], 39 | fullName; 40 | name = name.split( "." )[ 1 ]; 41 | fullName = namespace + "-" + name; 42 | 43 | if ( !prototype ) { 44 | prototype = base; 45 | base = $.Widget; 46 | } 47 | 48 | // create selector for plugin 49 | $.expr[ ":" ][ fullName ] = function( elem ) { 50 | return !!$.data( elem, name ); 51 | }; 52 | 53 | $[ namespace ] = $[ namespace ] || {}; 54 | $[ namespace ][ name ] = function( options, element ) { 55 | // allow instantiation without initializing for simple inheritance 56 | if ( arguments.length ) { 57 | this._createWidget( options, element ); 58 | } 59 | }; 60 | 61 | var basePrototype = new base(); 62 | // we need to make the options hash a property directly on the new instance 63 | // otherwise we'll modify the options hash on the prototype that we're 64 | // inheriting from 65 | // $.each( basePrototype, function( key, val ) { 66 | // if ( $.isPlainObject(val) ) { 67 | // basePrototype[ key ] = $.extend( {}, val ); 68 | // } 69 | // }); 70 | basePrototype.options = $.extend( true, {}, basePrototype.options ); 71 | $[ namespace ][ name ].prototype = $.extend( true, basePrototype, { 72 | namespace: namespace, 73 | widgetName: name, 74 | widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, 75 | widgetBaseClass: fullName 76 | }, prototype ); 77 | 78 | $.widget.bridge( name, $[ namespace ][ name ] ); 79 | }; 80 | 81 | $.widget.bridge = function( name, object ) { 82 | $.fn[ name ] = function( options ) { 83 | var isMethodCall = typeof options === "string", 84 | args = Array.prototype.slice.call( arguments, 1 ), 85 | returnValue = this; 86 | 87 | // allow multiple hashes to be passed on init 88 | options = !isMethodCall && args.length ? 89 | $.extend.apply( null, [ true, options ].concat(args) ) : 90 | options; 91 | 92 | // prevent calls to internal methods 93 | if ( isMethodCall && options.charAt( 0 ) === "_" ) { 94 | return returnValue; 95 | } 96 | 97 | if ( isMethodCall ) { 98 | this.each(function() { 99 | var instance = $.data( this, name ), 100 | methodValue = instance && $.isFunction( instance[options] ) ? 101 | instance[ options ].apply( instance, args ) : 102 | instance; 103 | // TODO: add this back in 1.9 and use $.error() (see #5972) 104 | // if ( !instance ) { 105 | // throw "cannot call methods on " + name + " prior to initialization; " + 106 | // "attempted to call method '" + options + "'"; 107 | // } 108 | // if ( !$.isFunction( instance[options] ) ) { 109 | // throw "no such method '" + options + "' for " + name + " widget instance"; 110 | // } 111 | // var methodValue = instance[ options ].apply( instance, args ); 112 | if ( methodValue !== instance && methodValue !== undefined ) { 113 | returnValue = methodValue; 114 | return false; 115 | } 116 | }); 117 | } else { 118 | this.each(function() { 119 | var instance = $.data( this, name ); 120 | if ( instance ) { 121 | instance.option( options || {} )._init(); 122 | } else { 123 | $.data( this, name, new object( options, this ) ); 124 | } 125 | }); 126 | } 127 | 128 | return returnValue; 129 | }; 130 | }; 131 | 132 | $.Widget = function( options, element ) { 133 | // allow instantiation without initializing for simple inheritance 134 | if ( arguments.length ) { 135 | this._createWidget( options, element ); 136 | } 137 | }; 138 | 139 | $.Widget.prototype = { 140 | widgetName: "widget", 141 | widgetEventPrefix: "", 142 | options: { 143 | disabled: false 144 | }, 145 | _createWidget: function( options, element ) { 146 | // $.widget.bridge stores the plugin instance, but we do it anyway 147 | // so that it's stored even before the _create function runs 148 | $.data( element, this.widgetName, this ); 149 | this.element = $( element ); 150 | this.options = $.extend( true, {}, 151 | this.options, 152 | this._getCreateOptions(), 153 | options ); 154 | 155 | var self = this; 156 | this.element.bind( "remove." + this.widgetName, function() { 157 | self.destroy(); 158 | }); 159 | 160 | this._create(); 161 | this._trigger( "create" ); 162 | this._init(); 163 | }, 164 | _getCreateOptions: function() { 165 | return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ]; 166 | }, 167 | _create: function() {}, 168 | _init: function() {}, 169 | 170 | destroy: function() { 171 | this.element 172 | .unbind( "." + this.widgetName ) 173 | .removeData( this.widgetName ); 174 | this.widget() 175 | .unbind( "." + this.widgetName ) 176 | .removeAttr( "aria-disabled" ) 177 | .removeClass( 178 | this.widgetBaseClass + "-disabled " + 179 | "ui-state-disabled" ); 180 | }, 181 | 182 | widget: function() { 183 | return this.element; 184 | }, 185 | 186 | option: function( key, value ) { 187 | var options = key; 188 | 189 | if ( arguments.length === 0 ) { 190 | // don't return a reference to the internal hash 191 | return $.extend( {}, this.options ); 192 | } 193 | 194 | if (typeof key === "string" ) { 195 | if ( value === undefined ) { 196 | return this.options[ key ]; 197 | } 198 | options = {}; 199 | options[ key ] = value; 200 | } 201 | 202 | this._setOptions( options ); 203 | 204 | return this; 205 | }, 206 | _setOptions: function( options ) { 207 | var self = this; 208 | $.each( options, function( key, value ) { 209 | self._setOption( key, value ); 210 | }); 211 | 212 | return this; 213 | }, 214 | _setOption: function( key, value ) { 215 | this.options[ key ] = value; 216 | 217 | if ( key === "disabled" ) { 218 | this.widget() 219 | [ value ? "addClass" : "removeClass"]( 220 | this.widgetBaseClass + "-disabled" + " " + 221 | "ui-state-disabled" ) 222 | .attr( "aria-disabled", value ); 223 | } 224 | 225 | return this; 226 | }, 227 | 228 | enable: function() { 229 | return this._setOption( "disabled", false ); 230 | }, 231 | disable: function() { 232 | return this._setOption( "disabled", true ); 233 | }, 234 | 235 | _trigger: function( type, event, data ) { 236 | var callback = this.options[ type ]; 237 | 238 | event = $.Event( event ); 239 | event.type = ( type === this.widgetEventPrefix ? 240 | type : 241 | this.widgetEventPrefix + type ).toLowerCase(); 242 | data = data || {}; 243 | 244 | // copy original event properties over to the new event 245 | // this would happen if we could call $.event.fix instead of $.Event 246 | // but we don't have a way to force an event to be fixed multiple times 247 | if ( event.originalEvent ) { 248 | for ( var i = $.event.props.length, prop; i; ) { 249 | prop = $.event.props[ --i ]; 250 | event[ prop ] = event.originalEvent[ prop ]; 251 | } 252 | } 253 | 254 | this.element.trigger( event, data ); 255 | 256 | return !( $.isFunction(callback) && 257 | callback.call( this.element[0], event, data ) === false || 258 | event.isDefaultPrevented() ); 259 | } 260 | }; 261 | 262 | })( jQuery ); 263 | -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-bg_flat_75_ffffff_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-bg_flat_75_ffffff_40x100.png -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-bg_glass_75_dadada_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-bg_glass_75_dadada_1x400.png -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-icons_2e83ff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-icons_2e83ff_256x240.png -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-icons_454545_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-icons_454545_256x240.png -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-icons_888888_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-icons_888888_256x240.png -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-icons_cd0a0a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/jqueryui/1.8/themes/base/images/ui-icons_cd0a0a_256x240.png -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/jquery.ui.all.css: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery UI CSS Framework 1.8.13 3 | * 4 | * Copyright 2011, AUTHORS.txt (https://jqueryui.com/about) 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * https://jquery.org/license 7 | * 8 | * https://docs.jquery.com/UI/Theming 9 | */ 10 | @import "jquery.ui.base.css"; 11 | @import "jquery.ui.theme.css"; 12 | -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/jquery.ui.base.css: -------------------------------------------------------------------------------- 1 | @import url("jquery.ui.core.css"); 2 | @import url("jquery.ui.resizable.css"); 3 | @import url("jquery.ui.selectable.css"); 4 | @import url("jquery.ui.accordion.css"); 5 | @import url("jquery.ui.autocomplete.css"); 6 | @import url("jquery.ui.button.css"); 7 | @import url("jquery.ui.dialog.css"); 8 | @import url("jquery.ui.slider.css"); 9 | @import url("jquery.ui.tabs.css"); 10 | @import url("jquery.ui.datepicker.css"); 11 | @import url("jquery.ui.progressbar.css"); -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/jquery.ui.core.css: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery UI CSS Framework 1.8.13 3 | * 4 | * Copyright 2011, AUTHORS.txt (https://jqueryui.com/about) 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * https://jquery.org/license 7 | * 8 | * https://docs.jquery.com/UI/Theming/API 9 | */ 10 | 11 | /* Layout helpers 12 | ----------------------------------*/ 13 | .ui-helper-hidden { display: none; } 14 | .ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } 15 | .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } 16 | .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } 17 | .ui-helper-clearfix { display: inline-block; } 18 | /* required comment for clearfix to work in Opera \*/ 19 | * html .ui-helper-clearfix { height:1%; } 20 | .ui-helper-clearfix { display:block; } 21 | /* end clearfix */ 22 | .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } 23 | 24 | 25 | /* Interaction Cues 26 | ----------------------------------*/ 27 | .ui-state-disabled { cursor: default !important; } 28 | 29 | 30 | /* Icons 31 | ----------------------------------*/ 32 | 33 | /* states and images */ 34 | .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } 35 | 36 | 37 | /* Misc visuals 38 | ----------------------------------*/ 39 | 40 | /* Overlays */ 41 | .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } 42 | -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/jquery.ui.tabs.css: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery UI Tabs 1.8.13 3 | * 4 | * Copyright 2011, AUTHORS.txt (https://jqueryui.com/about) 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * https://jquery.org/license 7 | * 8 | * https://docs.jquery.com/UI/Tabs#theming 9 | */ 10 | .ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ 11 | .ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } 12 | .ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } 13 | .ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } 14 | .ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } 15 | .ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } 16 | .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ 17 | .ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } 18 | .ui-tabs .ui-tabs-hide { display: none !important; } 19 | -------------------------------------------------------------------------------- /src/main/webapp/resources/jqueryui/1.8/themes/base/jquery.ui.theme.css: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery UI CSS Framework 1.8.13 3 | * 4 | * Copyright 2011, AUTHORS.txt (https://jqueryui.com/about) 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * https://jquery.org/license 7 | * 8 | * https://docs.jquery.com/UI/Theming/API 9 | * 10 | * To view and modify this theme, visit https://jqueryui.com/themeroller/ 11 | */ 12 | 13 | 14 | /* Component containers 15 | ----------------------------------*/ 16 | .ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; } 17 | .ui-widget .ui-widget { font-size: 1em; } 18 | .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; } 19 | .ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(images/ui-bg_flat_75_ffffff_40x100.png)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; } 20 | .ui-widget-content a { color: #222222/*{fcContent}*/; } 21 | .ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; } 22 | .ui-widget-header a { color: #222222/*{fcHeader}*/; } 23 | 24 | /* Interaction states 25 | ----------------------------------*/ 26 | .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; } 27 | .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; } 28 | .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; } 29 | .ui-state-hover a, .ui-state-hover a:hover { color: #212121/*{fcHover}*/; text-decoration: none; } 30 | .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(images/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; } 31 | .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; } 32 | .ui-widget :active { outline: none; } 33 | 34 | /* Interaction Cues 35 | ----------------------------------*/ 36 | .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; } 37 | .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; } 38 | .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; } 39 | .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; } 40 | .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; } 41 | .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } 42 | .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } 43 | .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } 44 | 45 | /* Icons 46 | ----------------------------------*/ 47 | 48 | /* states and images */ 49 | .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; } 50 | .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; } 51 | .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; } 52 | .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; } 53 | .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; } 54 | .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; } 55 | .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; } 56 | .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; } 57 | 58 | /* positioning */ 59 | .ui-icon-carat-1-n { background-position: 0 0; } 60 | .ui-icon-carat-1-ne { background-position: -16px 0; } 61 | .ui-icon-carat-1-e { background-position: -32px 0; } 62 | .ui-icon-carat-1-se { background-position: -48px 0; } 63 | .ui-icon-carat-1-s { background-position: -64px 0; } 64 | .ui-icon-carat-1-sw { background-position: -80px 0; } 65 | .ui-icon-carat-1-w { background-position: -96px 0; } 66 | .ui-icon-carat-1-nw { background-position: -112px 0; } 67 | .ui-icon-carat-2-n-s { background-position: -128px 0; } 68 | .ui-icon-carat-2-e-w { background-position: -144px 0; } 69 | .ui-icon-triangle-1-n { background-position: 0 -16px; } 70 | .ui-icon-triangle-1-ne { background-position: -16px -16px; } 71 | .ui-icon-triangle-1-e { background-position: -32px -16px; } 72 | .ui-icon-triangle-1-se { background-position: -48px -16px; } 73 | .ui-icon-triangle-1-s { background-position: -64px -16px; } 74 | .ui-icon-triangle-1-sw { background-position: -80px -16px; } 75 | .ui-icon-triangle-1-w { background-position: -96px -16px; } 76 | .ui-icon-triangle-1-nw { background-position: -112px -16px; } 77 | .ui-icon-triangle-2-n-s { background-position: -128px -16px; } 78 | .ui-icon-triangle-2-e-w { background-position: -144px -16px; } 79 | .ui-icon-arrow-1-n { background-position: 0 -32px; } 80 | .ui-icon-arrow-1-ne { background-position: -16px -32px; } 81 | .ui-icon-arrow-1-e { background-position: -32px -32px; } 82 | .ui-icon-arrow-1-se { background-position: -48px -32px; } 83 | .ui-icon-arrow-1-s { background-position: -64px -32px; } 84 | .ui-icon-arrow-1-sw { background-position: -80px -32px; } 85 | .ui-icon-arrow-1-w { background-position: -96px -32px; } 86 | .ui-icon-arrow-1-nw { background-position: -112px -32px; } 87 | .ui-icon-arrow-2-n-s { background-position: -128px -32px; } 88 | .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } 89 | .ui-icon-arrow-2-e-w { background-position: -160px -32px; } 90 | .ui-icon-arrow-2-se-nw { background-position: -176px -32px; } 91 | .ui-icon-arrowstop-1-n { background-position: -192px -32px; } 92 | .ui-icon-arrowstop-1-e { background-position: -208px -32px; } 93 | .ui-icon-arrowstop-1-s { background-position: -224px -32px; } 94 | .ui-icon-arrowstop-1-w { background-position: -240px -32px; } 95 | .ui-icon-arrowthick-1-n { background-position: 0 -48px; } 96 | .ui-icon-arrowthick-1-ne { background-position: -16px -48px; } 97 | .ui-icon-arrowthick-1-e { background-position: -32px -48px; } 98 | .ui-icon-arrowthick-1-se { background-position: -48px -48px; } 99 | .ui-icon-arrowthick-1-s { background-position: -64px -48px; } 100 | .ui-icon-arrowthick-1-sw { background-position: -80px -48px; } 101 | .ui-icon-arrowthick-1-w { background-position: -96px -48px; } 102 | .ui-icon-arrowthick-1-nw { background-position: -112px -48px; } 103 | .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } 104 | .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } 105 | .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } 106 | .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } 107 | .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } 108 | .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } 109 | .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } 110 | .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } 111 | .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } 112 | .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } 113 | .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } 114 | .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } 115 | .ui-icon-arrowreturn-1-w { background-position: -64px -64px; } 116 | .ui-icon-arrowreturn-1-n { background-position: -80px -64px; } 117 | .ui-icon-arrowreturn-1-e { background-position: -96px -64px; } 118 | .ui-icon-arrowreturn-1-s { background-position: -112px -64px; } 119 | .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } 120 | .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } 121 | .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } 122 | .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } 123 | .ui-icon-arrow-4 { background-position: 0 -80px; } 124 | .ui-icon-arrow-4-diag { background-position: -16px -80px; } 125 | .ui-icon-extlink { background-position: -32px -80px; } 126 | .ui-icon-newwin { background-position: -48px -80px; } 127 | .ui-icon-refresh { background-position: -64px -80px; } 128 | .ui-icon-shuffle { background-position: -80px -80px; } 129 | .ui-icon-transfer-e-w { background-position: -96px -80px; } 130 | .ui-icon-transferthick-e-w { background-position: -112px -80px; } 131 | .ui-icon-folder-collapsed { background-position: 0 -96px; } 132 | .ui-icon-folder-open { background-position: -16px -96px; } 133 | .ui-icon-document { background-position: -32px -96px; } 134 | .ui-icon-document-b { background-position: -48px -96px; } 135 | .ui-icon-note { background-position: -64px -96px; } 136 | .ui-icon-mail-closed { background-position: -80px -96px; } 137 | .ui-icon-mail-open { background-position: -96px -96px; } 138 | .ui-icon-suitcase { background-position: -112px -96px; } 139 | .ui-icon-comment { background-position: -128px -96px; } 140 | .ui-icon-person { background-position: -144px -96px; } 141 | .ui-icon-print { background-position: -160px -96px; } 142 | .ui-icon-trash { background-position: -176px -96px; } 143 | .ui-icon-locked { background-position: -192px -96px; } 144 | .ui-icon-unlocked { background-position: -208px -96px; } 145 | .ui-icon-bookmark { background-position: -224px -96px; } 146 | .ui-icon-tag { background-position: -240px -96px; } 147 | .ui-icon-home { background-position: 0 -112px; } 148 | .ui-icon-flag { background-position: -16px -112px; } 149 | .ui-icon-calendar { background-position: -32px -112px; } 150 | .ui-icon-cart { background-position: -48px -112px; } 151 | .ui-icon-pencil { background-position: -64px -112px; } 152 | .ui-icon-clock { background-position: -80px -112px; } 153 | .ui-icon-disk { background-position: -96px -112px; } 154 | .ui-icon-calculator { background-position: -112px -112px; } 155 | .ui-icon-zoomin { background-position: -128px -112px; } 156 | .ui-icon-zoomout { background-position: -144px -112px; } 157 | .ui-icon-search { background-position: -160px -112px; } 158 | .ui-icon-wrench { background-position: -176px -112px; } 159 | .ui-icon-gear { background-position: -192px -112px; } 160 | .ui-icon-heart { background-position: -208px -112px; } 161 | .ui-icon-star { background-position: -224px -112px; } 162 | .ui-icon-link { background-position: -240px -112px; } 163 | .ui-icon-cancel { background-position: 0 -128px; } 164 | .ui-icon-plus { background-position: -16px -128px; } 165 | .ui-icon-plusthick { background-position: -32px -128px; } 166 | .ui-icon-minus { background-position: -48px -128px; } 167 | .ui-icon-minusthick { background-position: -64px -128px; } 168 | .ui-icon-close { background-position: -80px -128px; } 169 | .ui-icon-closethick { background-position: -96px -128px; } 170 | .ui-icon-key { background-position: -112px -128px; } 171 | .ui-icon-lightbulb { background-position: -128px -128px; } 172 | .ui-icon-scissors { background-position: -144px -128px; } 173 | .ui-icon-clipboard { background-position: -160px -128px; } 174 | .ui-icon-copy { background-position: -176px -128px; } 175 | .ui-icon-contact { background-position: -192px -128px; } 176 | .ui-icon-image { background-position: -208px -128px; } 177 | .ui-icon-video { background-position: -224px -128px; } 178 | .ui-icon-script { background-position: -240px -128px; } 179 | .ui-icon-alert { background-position: 0 -144px; } 180 | .ui-icon-info { background-position: -16px -144px; } 181 | .ui-icon-notice { background-position: -32px -144px; } 182 | .ui-icon-help { background-position: -48px -144px; } 183 | .ui-icon-check { background-position: -64px -144px; } 184 | .ui-icon-bullet { background-position: -80px -144px; } 185 | .ui-icon-radio-off { background-position: -96px -144px; } 186 | .ui-icon-radio-on { background-position: -112px -144px; } 187 | .ui-icon-pin-w { background-position: -128px -144px; } 188 | .ui-icon-pin-s { background-position: -144px -144px; } 189 | .ui-icon-play { background-position: 0 -160px; } 190 | .ui-icon-pause { background-position: -16px -160px; } 191 | .ui-icon-seek-next { background-position: -32px -160px; } 192 | .ui-icon-seek-prev { background-position: -48px -160px; } 193 | .ui-icon-seek-end { background-position: -64px -160px; } 194 | .ui-icon-seek-start { background-position: -80px -160px; } 195 | /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ 196 | .ui-icon-seek-first { background-position: -80px -160px; } 197 | .ui-icon-stop { background-position: -96px -160px; } 198 | .ui-icon-eject { background-position: -112px -160px; } 199 | .ui-icon-volume-off { background-position: -128px -160px; } 200 | .ui-icon-volume-on { background-position: -144px -160px; } 201 | .ui-icon-power { background-position: 0 -176px; } 202 | .ui-icon-signal-diag { background-position: -16px -176px; } 203 | .ui-icon-signal { background-position: -32px -176px; } 204 | .ui-icon-battery-0 { background-position: -48px -176px; } 205 | .ui-icon-battery-1 { background-position: -64px -176px; } 206 | .ui-icon-battery-2 { background-position: -80px -176px; } 207 | .ui-icon-battery-3 { background-position: -96px -176px; } 208 | .ui-icon-circle-plus { background-position: 0 -192px; } 209 | .ui-icon-circle-minus { background-position: -16px -192px; } 210 | .ui-icon-circle-close { background-position: -32px -192px; } 211 | .ui-icon-circle-triangle-e { background-position: -48px -192px; } 212 | .ui-icon-circle-triangle-s { background-position: -64px -192px; } 213 | .ui-icon-circle-triangle-w { background-position: -80px -192px; } 214 | .ui-icon-circle-triangle-n { background-position: -96px -192px; } 215 | .ui-icon-circle-arrow-e { background-position: -112px -192px; } 216 | .ui-icon-circle-arrow-s { background-position: -128px -192px; } 217 | .ui-icon-circle-arrow-w { background-position: -144px -192px; } 218 | .ui-icon-circle-arrow-n { background-position: -160px -192px; } 219 | .ui-icon-circle-zoomin { background-position: -176px -192px; } 220 | .ui-icon-circle-zoomout { background-position: -192px -192px; } 221 | .ui-icon-circle-check { background-position: -208px -192px; } 222 | .ui-icon-circlesmall-plus { background-position: 0 -208px; } 223 | .ui-icon-circlesmall-minus { background-position: -16px -208px; } 224 | .ui-icon-circlesmall-close { background-position: -32px -208px; } 225 | .ui-icon-squaresmall-plus { background-position: -48px -208px; } 226 | .ui-icon-squaresmall-minus { background-position: -64px -208px; } 227 | .ui-icon-squaresmall-close { background-position: -80px -208px; } 228 | .ui-icon-grip-dotted-vertical { background-position: 0 -224px; } 229 | .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } 230 | .ui-icon-grip-solid-vertical { background-position: -32px -224px; } 231 | .ui-icon-grip-solid-horizontal { background-position: -48px -224px; } 232 | .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } 233 | .ui-icon-grip-diagonal-se { background-position: -80px -224px; } 234 | 235 | 236 | /* Misc visuals 237 | ----------------------------------*/ 238 | 239 | /* Corner radius */ 240 | .ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; } 241 | .ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; } 242 | .ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; } 243 | .ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; } 244 | .ui-corner-top { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; } 245 | .ui-corner-bottom { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; } 246 | .ui-corner-right { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; } 247 | .ui-corner-left { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; } 248 | .ui-corner-all { -moz-border-radius: 4px/*{cornerRadius}*/; -webkit-border-radius: 4px/*{cornerRadius}*/; border-radius: 4px/*{cornerRadius}*/; } 249 | 250 | /* Overlays */ 251 | .ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; } 252 | .ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; } -------------------------------------------------------------------------------- /src/main/webapp/resources/json2.js: -------------------------------------------------------------------------------- 1 | /* 2 | https://www.JSON.org/json2.js 3 | 2010-03-20 4 | 5 | Public Domain. 6 | 7 | NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. 8 | 9 | See https://www.JSON.org/js.html 10 | 11 | 12 | This code should be minified before deployment. 13 | See https://javascript.crockford.com/jsmin.html 14 | 15 | USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO 16 | NOT CONTROL. 17 | 18 | 19 | This file creates a global JSON object containing two methods: stringify 20 | and parse. 21 | 22 | JSON.stringify(value, replacer, space) 23 | value any JavaScript value, usually an object or array. 24 | 25 | replacer an optional parameter that determines how object 26 | values are stringified for objects. It can be a 27 | function or an array of strings. 28 | 29 | space an optional parameter that specifies the indentation 30 | of nested structures. If it is omitted, the text will 31 | be packed without extra whitespace. If it is a number, 32 | it will specify the number of spaces to indent at each 33 | level. If it is a string (such as '\t' or ' '), 34 | it contains the characters used to indent at each level. 35 | 36 | This method produces a JSON text from a JavaScript value. 37 | 38 | When an object value is found, if the object contains a toJSON 39 | method, its toJSON method will be called and the result will be 40 | stringified. A toJSON method does not serialize: it returns the 41 | value represented by the name/value pair that should be serialized, 42 | or undefined if nothing should be serialized. The toJSON method 43 | will be passed the key associated with the value, and this will be 44 | bound to the value 45 | 46 | For example, this would serialize Dates as ISO strings. 47 | 48 | Date.prototype.toJSON = function (key) { 49 | function f(n) { 50 | // Format integers to have at least two digits. 51 | return n < 10 ? '0' + n : n; 52 | } 53 | 54 | return this.getUTCFullYear() + '-' + 55 | f(this.getUTCMonth() + 1) + '-' + 56 | f(this.getUTCDate()) + 'T' + 57 | f(this.getUTCHours()) + ':' + 58 | f(this.getUTCMinutes()) + ':' + 59 | f(this.getUTCSeconds()) + 'Z'; 60 | }; 61 | 62 | You can provide an optional replacer method. It will be passed the 63 | key and value of each member, with this bound to the containing 64 | object. The value that is returned from your method will be 65 | serialized. If your method returns undefined, then the member will 66 | be excluded from the serialization. 67 | 68 | If the replacer parameter is an array of strings, then it will be 69 | used to select the members to be serialized. It filters the results 70 | such that only members with keys listed in the replacer array are 71 | stringified. 72 | 73 | Values that do not have JSON representations, such as undefined or 74 | functions, will not be serialized. Such values in objects will be 75 | dropped; in arrays they will be replaced with null. You can use 76 | a replacer function to replace those with JSON values. 77 | JSON.stringify(undefined) returns undefined. 78 | 79 | The optional space parameter produces a stringification of the 80 | value that is filled with line breaks and indentation to make it 81 | easier to read. 82 | 83 | If the space parameter is a non-empty string, then that string will 84 | be used for indentation. If the space parameter is a number, then 85 | the indentation will be that many spaces. 86 | 87 | Example: 88 | 89 | text = JSON.stringify(['e', {pluribus: 'unum'}]); 90 | // text is '["e",{"pluribus":"unum"}]' 91 | 92 | 93 | text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); 94 | // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' 95 | 96 | text = JSON.stringify([new Date()], function (key, value) { 97 | return this[key] instanceof Date ? 98 | 'Date(' + this[key] + ')' : value; 99 | }); 100 | // text is '["Date(---current time---)"]' 101 | 102 | 103 | JSON.parse(text, reviver) 104 | This method parses a JSON text to produce an object or array. 105 | It can throw a SyntaxError exception. 106 | 107 | The optional reviver parameter is a function that can filter and 108 | transform the results. It receives each of the keys and values, 109 | and its return value is used instead of the original value. 110 | If it returns what it received, then the structure is not modified. 111 | If it returns undefined then the member is deleted. 112 | 113 | Example: 114 | 115 | // Parse the text. Values that look like ISO date strings will 116 | // be converted to Date objects. 117 | 118 | myData = JSON.parse(text, function (key, value) { 119 | var a; 120 | if (typeof value === 'string') { 121 | a = 122 | /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); 123 | if (a) { 124 | return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], 125 | +a[5], +a[6])); 126 | } 127 | } 128 | return value; 129 | }); 130 | 131 | myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { 132 | var d; 133 | if (typeof value === 'string' && 134 | value.slice(0, 5) === 'Date(' && 135 | value.slice(-1) === ')') { 136 | d = new Date(value.slice(5, -1)); 137 | if (d) { 138 | return d; 139 | } 140 | } 141 | return value; 142 | }); 143 | 144 | 145 | This is a reference implementation. You are free to copy, modify, or 146 | redistribute. 147 | */ 148 | 149 | /*jslint evil: true, strict: false */ 150 | 151 | /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, 152 | call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, 153 | getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, 154 | lastIndex, length, parse, prototype, push, replace, slice, stringify, 155 | test, toJSON, toString, valueOf 156 | */ 157 | 158 | 159 | // Create a JSON object only if one does not already exist. We create the 160 | // methods in a closure to avoid creating global variables. 161 | 162 | if (!this.JSON) { 163 | this.JSON = {}; 164 | } 165 | 166 | (function () { 167 | 168 | function f(n) { 169 | // Format integers to have at least two digits. 170 | return n < 10 ? '0' + n : n; 171 | } 172 | 173 | if (typeof Date.prototype.toJSON !== 'function') { 174 | 175 | Date.prototype.toJSON = function (key) { 176 | 177 | return isFinite(this.valueOf()) ? 178 | this.getUTCFullYear() + '-' + 179 | f(this.getUTCMonth() + 1) + '-' + 180 | f(this.getUTCDate()) + 'T' + 181 | f(this.getUTCHours()) + ':' + 182 | f(this.getUTCMinutes()) + ':' + 183 | f(this.getUTCSeconds()) + 'Z' : null; 184 | }; 185 | 186 | String.prototype.toJSON = 187 | Number.prototype.toJSON = 188 | Boolean.prototype.toJSON = function (key) { 189 | return this.valueOf(); 190 | }; 191 | } 192 | 193 | var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, 194 | escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, 195 | gap, 196 | indent, 197 | meta = { // table of character substitutions 198 | '\b': '\\b', 199 | '\t': '\\t', 200 | '\n': '\\n', 201 | '\f': '\\f', 202 | '\r': '\\r', 203 | '"' : '\\"', 204 | '\\': '\\\\' 205 | }, 206 | rep; 207 | 208 | 209 | function quote(string) { 210 | 211 | // If the string contains no control characters, no quote characters, and no 212 | // backslash characters, then we can safely slap some quotes around it. 213 | // Otherwise we must also replace the offending characters with safe escape 214 | // sequences. 215 | 216 | escapable.lastIndex = 0; 217 | return escapable.test(string) ? 218 | '"' + string.replace(escapable, function (a) { 219 | var c = meta[a]; 220 | return typeof c === 'string' ? c : 221 | '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); 222 | }) + '"' : 223 | '"' + string + '"'; 224 | } 225 | 226 | 227 | function str(key, holder) { 228 | 229 | // Produce a string from holder[key]. 230 | 231 | var i, // The loop counter. 232 | k, // The member key. 233 | v, // The member value. 234 | length, 235 | mind = gap, 236 | partial, 237 | value = holder[key]; 238 | 239 | // If the value has a toJSON method, call it to obtain a replacement value. 240 | 241 | if (value && typeof value === 'object' && 242 | typeof value.toJSON === 'function') { 243 | value = value.toJSON(key); 244 | } 245 | 246 | // If we were called with a replacer function, then call the replacer to 247 | // obtain a replacement value. 248 | 249 | if (typeof rep === 'function') { 250 | value = rep.call(holder, key, value); 251 | } 252 | 253 | // What happens next depends on the value's type. 254 | 255 | switch (typeof value) { 256 | case 'string': 257 | return quote(value); 258 | 259 | case 'number': 260 | 261 | // JSON numbers must be finite. Encode non-finite numbers as null. 262 | 263 | return isFinite(value) ? String(value) : 'null'; 264 | 265 | case 'boolean': 266 | case 'null': 267 | 268 | // If the value is a boolean or null, convert it to a string. Note: 269 | // typeof null does not produce 'null'. The case is included here in 270 | // the remote chance that this gets fixed someday. 271 | 272 | return String(value); 273 | 274 | // If the type is 'object', we might be dealing with an object or an array or 275 | // null. 276 | 277 | case 'object': 278 | 279 | // Due to a specification blunder in ECMAScript, typeof null is 'object', 280 | // so watch out for that case. 281 | 282 | if (!value) { 283 | return 'null'; 284 | } 285 | 286 | // Make an array to hold the partial results of stringifying this object value. 287 | 288 | gap += indent; 289 | partial = []; 290 | 291 | // Is the value an array? 292 | 293 | if (Object.prototype.toString.apply(value) === '[object Array]') { 294 | 295 | // The value is an array. Stringify every element. Use null as a placeholder 296 | // for non-JSON values. 297 | 298 | length = value.length; 299 | for (i = 0; i < length; i += 1) { 300 | partial[i] = str(i, value) || 'null'; 301 | } 302 | 303 | // Join all of the elements together, separated with commas, and wrap them in 304 | // brackets. 305 | 306 | v = partial.length === 0 ? '[]' : 307 | gap ? '[\n' + gap + 308 | partial.join(',\n' + gap) + '\n' + 309 | mind + ']' : 310 | '[' + partial.join(',') + ']'; 311 | gap = mind; 312 | return v; 313 | } 314 | 315 | // If the replacer is an array, use it to select the members to be stringified. 316 | 317 | if (rep && typeof rep === 'object') { 318 | length = rep.length; 319 | for (i = 0; i < length; i += 1) { 320 | k = rep[i]; 321 | if (typeof k === 'string') { 322 | v = str(k, value); 323 | if (v) { 324 | partial.push(quote(k) + (gap ? ': ' : ':') + v); 325 | } 326 | } 327 | } 328 | } else { 329 | 330 | // Otherwise, iterate through all of the keys in the object. 331 | 332 | for (k in value) { 333 | if (Object.hasOwnProperty.call(value, k)) { 334 | v = str(k, value); 335 | if (v) { 336 | partial.push(quote(k) + (gap ? ': ' : ':') + v); 337 | } 338 | } 339 | } 340 | } 341 | 342 | // Join all of the member texts together, separated with commas, 343 | // and wrap them in braces. 344 | 345 | v = partial.length === 0 ? '{}' : 346 | gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + 347 | mind + '}' : '{' + partial.join(',') + '}'; 348 | gap = mind; 349 | return v; 350 | } 351 | } 352 | 353 | // If the JSON object does not yet have a stringify method, give it one. 354 | 355 | if (typeof JSON.stringify !== 'function') { 356 | JSON.stringify = function (value, replacer, space) { 357 | 358 | // The stringify method takes a value and an optional replacer, and an optional 359 | // space parameter, and returns a JSON text. The replacer can be a function 360 | // that can replace values, or an array of strings that will select the keys. 361 | // A default replacer method can be provided. Use of the space parameter can 362 | // produce text that is more easily readable. 363 | 364 | var i; 365 | gap = ''; 366 | indent = ''; 367 | 368 | // If the space parameter is a number, make an indent string containing that 369 | // many spaces. 370 | 371 | if (typeof space === 'number') { 372 | for (i = 0; i < space; i += 1) { 373 | indent += ' '; 374 | } 375 | 376 | // If the space parameter is a string, it will be used as the indent string. 377 | 378 | } else if (typeof space === 'string') { 379 | indent = space; 380 | } 381 | 382 | // If there is a replacer, it must be a function or an array. 383 | // Otherwise, throw an error. 384 | 385 | rep = replacer; 386 | if (replacer && typeof replacer !== 'function' && 387 | (typeof replacer !== 'object' || 388 | typeof replacer.length !== 'number')) { 389 | throw new Error('JSON.stringify'); 390 | } 391 | 392 | // Make a fake root object containing our value under the key of ''. 393 | // Return the result of stringifying the value. 394 | 395 | return str('', {'': value}); 396 | }; 397 | } 398 | 399 | 400 | // If the JSON object does not yet have a parse method, give it one. 401 | 402 | if (typeof JSON.parse !== 'function') { 403 | JSON.parse = function (text, reviver) { 404 | 405 | // The parse method takes a text and an optional reviver function, and returns 406 | // a JavaScript value if the text is a valid JSON text. 407 | 408 | var j; 409 | 410 | function walk(holder, key) { 411 | 412 | // The walk method is used to recursively walk the resulting structure so 413 | // that modifications can be made. 414 | 415 | var k, v, value = holder[key]; 416 | if (value && typeof value === 'object') { 417 | for (k in value) { 418 | if (Object.hasOwnProperty.call(value, k)) { 419 | v = walk(value, k); 420 | if (v !== undefined) { 421 | value[k] = v; 422 | } else { 423 | delete value[k]; 424 | } 425 | } 426 | } 427 | } 428 | return reviver.call(holder, key, value); 429 | } 430 | 431 | 432 | // Parsing happens in four stages. In the first stage, we replace certain 433 | // Unicode characters with escape sequences. JavaScript handles many characters 434 | // incorrectly, either silently deleting them, or treating them as line endings. 435 | 436 | text = String(text); 437 | cx.lastIndex = 0; 438 | if (cx.test(text)) { 439 | text = text.replace(cx, function (a) { 440 | return '\\u' + 441 | ('0000' + a.charCodeAt(0).toString(16)).slice(-4); 442 | }); 443 | } 444 | 445 | // In the second stage, we run the text against regular expressions that look 446 | // for non-JSON patterns. We are especially concerned with '()' and 'new' 447 | // because they can cause invocation, and '=' because it can cause mutation. 448 | // But just to be safe, we want to reject all unexpected forms. 449 | 450 | // We split the second stage into 4 regexp operations in order to work around 451 | // crippling inefficiencies in IE's and Safari's regexp engines. First we 452 | // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we 453 | // replace all simple value tokens with ']' characters. Third, we delete all 454 | // open brackets that follow a colon or comma or that begin the text. Finally, 455 | // we look to see that the remaining characters are only whitespace or ']' or 456 | // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. 457 | 458 | if (/^[\],:{}\s]*$/. 459 | test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). 460 | replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). 461 | replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { 462 | 463 | // In the third stage we use the eval function to compile the text into a 464 | // JavaScript structure. The '{' operator is subject to a syntactic ambiguity 465 | // in JavaScript: it can begin a block or an object literal. We wrap the text 466 | // in parens to eliminate the ambiguity. 467 | 468 | j = eval('(' + text + ')'); 469 | 470 | // In the optional fourth stage, we recursively walk the new structure, passing 471 | // each name/value pair to a reviver function for possible transformation. 472 | 473 | return typeof reviver === 'function' ? 474 | walk({'': j}, '') : j; 475 | } 476 | 477 | // If the text is not JSON parseable, then a SyntaxError is thrown. 478 | 479 | throw new SyntaxError('JSON.parse'); 480 | }; 481 | } 482 | }()); 483 | -------------------------------------------------------------------------------- /src/main/webapp/resources/messages/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/messages/error.png -------------------------------------------------------------------------------- /src/main/webapp/resources/messages/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/messages/info.png -------------------------------------------------------------------------------- /src/main/webapp/resources/messages/messages.css: -------------------------------------------------------------------------------- 1 | div.info,div.success,div.warning,div.error { 2 | border: 1px solid; 3 | margin: 10px 0px; 4 | padding: 15px 10px 15px 50px; 5 | background-repeat: no-repeat; 6 | background-position: 10px center; 7 | } 8 | 9 | div.info { 10 | color: #00529B; 11 | background-color: #BDE5F8; 12 | background-image: url('info.png'); 13 | } 14 | 15 | div.success { 16 | color: #4F8A10; 17 | background-color: #DFF2BF; 18 | background-image: url('success.png'); 19 | } 20 | 21 | div.warning { 22 | color: #9F6000; 23 | background-color: #FEEFB3; 24 | background-image: url('warning.png'); 25 | } 26 | 27 | div.error { 28 | color: #D8000C; 29 | background-color: #FFBABA; 30 | background-image: url('error.png'); 31 | } 32 | 33 | span { 34 | margin: 5px 5px 5px 5px; 35 | } 36 | 37 | span.success { 38 | color: #4F8A10; 39 | } 40 | 41 | span.error { 42 | color: #D8000C; 43 | } 44 | 45 | body { 46 | font-family: Lucida Grande, sans-serif; 47 | font-size: .75em; 48 | margin: 1em auto; 49 | width: 763px; 50 | } 51 | 52 | ul li { 53 | padding: 5px; 54 | } -------------------------------------------------------------------------------- /src/main/webapp/resources/messages/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/messages/success.png -------------------------------------------------------------------------------- /src/main/webapp/resources/messages/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-mvc-showcase/71d8c7e3432b226f09092dd13a7cfe2298fdd265/src/main/webapp/resources/messages/warning.png -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/AbstractContextControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.samples.mvc.config.WebMvcConfig; 5 | import org.springframework.test.context.ContextConfiguration; 6 | import org.springframework.test.context.web.WebAppConfiguration; 7 | import org.springframework.web.context.WebApplicationContext; 8 | 9 | @WebAppConfiguration 10 | @ContextConfiguration(classes = WebMvcConfig.class) 11 | public class AbstractContextControllerTests { 12 | 13 | @Autowired 14 | protected WebApplicationContext wac; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/async/CallableControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.async; 2 | 3 | import static org.hamcrest.Matchers.instanceOf; 4 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; 5 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 6 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 7 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl; 8 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; 9 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; 10 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 11 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; 12 | 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | import org.junit.runner.RunWith; 16 | import org.springframework.samples.mvc.AbstractContextControllerTests; 17 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 18 | import org.springframework.test.web.servlet.MockMvc; 19 | import org.springframework.test.web.servlet.MvcResult; 20 | 21 | @RunWith(SpringJUnit4ClassRunner.class) 22 | public class CallableControllerTests extends AbstractContextControllerTests { 23 | 24 | private MockMvc mockMvc; 25 | 26 | @Before 27 | public void setup() throws Exception { 28 | this.mockMvc = webAppContextSetup(this.wac).build(); 29 | } 30 | 31 | @Test 32 | public void responseBody() throws Exception { 33 | MvcResult mvcResult = this.mockMvc.perform(get("/async/callable/response-body")) 34 | .andExpect(request().asyncStarted()) 35 | .andExpect(request().asyncResult("Callable result")) 36 | .andReturn(); 37 | 38 | this.mockMvc.perform(asyncDispatch(mvcResult)) 39 | .andExpect(status().isOk()) 40 | .andExpect(content().contentType("text/plain;charset=ISO-8859-1")) 41 | .andExpect(content().string("Callable result")); 42 | } 43 | 44 | @Test 45 | public void view() throws Exception { 46 | MvcResult mvcResult = this.mockMvc.perform(get("/async/callable/view")) 47 | .andExpect(request().asyncStarted()) 48 | .andExpect(request().asyncResult("views/html")) 49 | .andReturn(); 50 | 51 | this.mockMvc.perform(asyncDispatch(mvcResult)) 52 | .andExpect(status().isOk()) 53 | .andExpect(forwardedUrl("/WEB-INF/views/views/html.jsp")) 54 | .andExpect(model().attribute("foo", "bar")) 55 | .andExpect(model().attribute("fruit", "apple")); 56 | } 57 | 58 | @Test 59 | public void exception() throws Exception { 60 | MvcResult mvcResult = this.mockMvc.perform(get("/async/callable/exception")) 61 | .andExpect(request().asyncStarted()) 62 | .andExpect(request().asyncResult(instanceOf(IllegalStateException.class))) 63 | .andReturn(); 64 | 65 | this.mockMvc.perform(asyncDispatch(mvcResult)) 66 | .andExpect(status().isOk()) 67 | .andExpect(content().contentType("text/plain;charset=ISO-8859-1")) 68 | .andExpect(content().string("Handled exception: Callable error")); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/async/DeferredResultControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.async; 2 | 3 | import static org.hamcrest.Matchers.instanceOf; 4 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; 5 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 6 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 7 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl; 8 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; 9 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; 10 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 11 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; 12 | 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | import org.junit.runner.RunWith; 16 | import org.springframework.samples.mvc.AbstractContextControllerTests; 17 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 18 | import org.springframework.test.web.servlet.MockMvc; 19 | import org.springframework.test.web.servlet.MvcResult; 20 | import org.springframework.web.servlet.ModelAndView; 21 | 22 | @RunWith(SpringJUnit4ClassRunner.class) 23 | public class DeferredResultControllerTests extends AbstractContextControllerTests { 24 | 25 | private MockMvc mockMvc; 26 | 27 | @Before 28 | public void setup() throws Exception { 29 | this.mockMvc = webAppContextSetup(this.wac).build(); 30 | } 31 | 32 | @Test 33 | public void responseBody() throws Exception { 34 | MvcResult mvcResult = this.mockMvc.perform(get("/async/deferred-result/response-body")) 35 | .andExpect(status().isOk()) 36 | .andExpect(request().asyncStarted()) 37 | .andExpect(request().asyncResult("Deferred result")) 38 | .andReturn(); 39 | 40 | this.mockMvc.perform(asyncDispatch(mvcResult)) 41 | .andExpect(status().isOk()) 42 | .andExpect(content().contentType("text/plain;charset=ISO-8859-1")) 43 | .andExpect(content().string("Deferred result")); 44 | } 45 | 46 | @Test 47 | public void view() throws Exception { 48 | MvcResult mvcResult = this.mockMvc.perform(get("/async/deferred-result/model-and-view")) 49 | .andExpect(status().isOk()) 50 | .andExpect(request().asyncStarted()) 51 | .andExpect(request().asyncResult(instanceOf(ModelAndView.class))) 52 | .andReturn(); 53 | 54 | this.mockMvc.perform(asyncDispatch(mvcResult)) 55 | .andExpect(status().isOk()) 56 | .andExpect(forwardedUrl("/WEB-INF/views/views/html.jsp")) 57 | .andExpect(model().attributeExists("javaBean")); 58 | } 59 | 60 | @Test 61 | public void exception() throws Exception { 62 | MvcResult mvcResult = this.mockMvc.perform(get("/async/deferred-result/exception")) 63 | .andExpect(status().isOk()) 64 | .andExpect(request().asyncStarted()) 65 | .andExpect(request().asyncResult(instanceOf(IllegalStateException.class))) 66 | .andReturn(); 67 | 68 | this.mockMvc.perform(asyncDispatch(mvcResult)) 69 | .andExpect(status().isOk()) 70 | .andExpect(content().contentType("text/plain;charset=ISO-8859-1")) 71 | .andExpect(content().string("Handled exception: DeferredResult error")); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/convert/ConvertControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.convert; 2 | 3 | import static org.hamcrest.Matchers.startsWith; 4 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 5 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 6 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 7 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; 8 | 9 | import java.util.Calendar; 10 | import java.util.Date; 11 | import java.util.TimeZone; 12 | 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | import org.springframework.format.support.DefaultFormattingConversionService; 16 | import org.springframework.format.support.FormattingConversionService; 17 | import org.springframework.test.web.servlet.MockMvc; 18 | 19 | public class ConvertControllerTests { 20 | 21 | private MockMvc mockMvc; 22 | 23 | @Before 24 | public void setup() throws Exception { 25 | FormattingConversionService cs = new DefaultFormattingConversionService(); 26 | cs.addFormatterForFieldAnnotation(new MaskFormatAnnotationFormatterFactory()); 27 | 28 | this.mockMvc = standaloneSetup(new ConvertController()) 29 | .setConversionService(cs) 30 | .alwaysExpect(status().isOk()) 31 | .build(); 32 | } 33 | 34 | @Test 35 | public void primitive() throws Exception { 36 | this.mockMvc.perform(get("/convert/primitive").param("value", "3")) 37 | .andExpect(content().string("Converted primitive 3")); 38 | } 39 | 40 | @Test 41 | public void date() throws Exception { 42 | String timezone = getTimezone(2010, 7, 4); 43 | this.mockMvc.perform(get("/convert/date/2010-07-04")) 44 | .andExpect(content().string("Converted date Sun Jul 04 00:00:00 " + timezone + " 2010")); 45 | } 46 | 47 | @Test 48 | public void collection() throws Exception { 49 | this.mockMvc.perform(get("/convert/collection?values=1&values=2&values=3&values=4&values=5")) 50 | .andExpect(content().string("Converted collection [1, 2, 3, 4, 5]")); 51 | } 52 | 53 | @Test 54 | public void collection2() throws Exception { 55 | this.mockMvc.perform(get("/convert/collection?values=1,2,3,4,5")) 56 | .andExpect(content().string("Converted collection [1, 2, 3, 4, 5]")); 57 | } 58 | 59 | @Test 60 | public void formattedCollection() throws Exception { 61 | String timezone2010 = getTimezone(2010, 7, 4); 62 | String timezone2011 = getTimezone(2011, 7, 4); 63 | this.mockMvc.perform(get("/convert/formattedCollection?values=2010-07-04,2011-07-04")) 64 | .andExpect(content().string( 65 | "Converted formatted collection [Sun Jul 04 00:00:00 " 66 | + timezone2010 + " 2010, Mon Jul 04 00:00:00 " + timezone2011 + " 2011]")); 67 | } 68 | 69 | @Test 70 | public void valueOf() throws Exception { 71 | this.mockMvc.perform(get("/convert/value?value=123456789")) 72 | .andExpect(content().string(startsWith( 73 | "Converted value object org.springframework.samples.mvc.convert.SocialSecurityNumber"))); 74 | } 75 | 76 | @Test 77 | public void custom() throws Exception { 78 | this.mockMvc.perform(get("/convert/custom?value=123-45-6789")) 79 | .andExpect(content().string("Converted '123456789' with a custom converter")); 80 | } 81 | 82 | @Test 83 | public void beanPrimitive() throws Exception { 84 | this.mockMvc.perform(get("/convert/bean?primitive=3")) 85 | .andExpect(content().string("Converted JavaBean primitive=3")); 86 | } 87 | 88 | @Test 89 | public void beanDate() throws Exception { 90 | String timezone = getTimezone(2010, 7, 4); 91 | this.mockMvc.perform(get("/convert/bean?date=2010-07-04")) 92 | .andExpect(content().string("Converted JavaBean date=Sun Jul 04 00:00:00 " + timezone + " 2010")); 93 | } 94 | 95 | @Test 96 | public void beanMasked() throws Exception { 97 | this.mockMvc.perform(get("/convert/bean?masked=(205) 333-3333")) 98 | .andExpect(content().string("Converted JavaBean masked=2053333333")); 99 | } 100 | 101 | @Test 102 | public void beanCollection() throws Exception { 103 | this.mockMvc.perform(get("/convert/bean?list[0]=1&list[1]=2&list[2]=3")) 104 | .andExpect(content().string("Converted JavaBean list=[1, 2, 3]")); 105 | } 106 | 107 | @Test 108 | public void beanFormattedCollection() throws Exception { 109 | String timezone2010 = getTimezone(2010, 7, 4); 110 | String timezone2011 = getTimezone(2011, 7, 4); 111 | this.mockMvc.perform(get("/convert/bean?formattedList[0]=2010-07-04&formattedList[1]=2011-07-04")) 112 | .andExpect(content().string( 113 | "Converted JavaBean formattedList=[Sun Jul 04 00:00:00 " + timezone2010 114 | + " 2010, Mon Jul 04 00:00:00 " + timezone2011 + " 2011]")); 115 | } 116 | 117 | @Test 118 | public void beanMap() throws Exception { 119 | this.mockMvc.perform(get("/convert/bean?map[0]=apple&map[1]=pear")) 120 | .andExpect(content().string("Converted JavaBean map={0=apple, 1=pear}")); 121 | } 122 | 123 | @Test 124 | public void beanNested() throws Exception { 125 | this.mockMvc.perform(get("/convert/bean?nested.foo=bar&nested.list[0].foo=baz&nested.map[key].list[0].foo=bip")) 126 | .andExpect(content().string( 127 | "Converted JavaBean nested=NestedBean foo=bar list=[NestedBean foo=baz] map={key=NestedBean list=[NestedBean foo=bip]}")); 128 | } 129 | 130 | private String getTimezone(int year, int month, int day) 131 | { 132 | Calendar calendar = Calendar.getInstance(); 133 | calendar.set(Calendar.YEAR, year); 134 | calendar.set(Calendar.MONTH, month); 135 | calendar.set(Calendar.DAY_OF_MONTH, day); 136 | Date date = calendar.getTime(); 137 | TimeZone timezone = TimeZone.getDefault(); 138 | boolean inDaylight = timezone.inDaylightTime(date); 139 | return timezone.getDisplayName(inDaylight, TimeZone.SHORT); 140 | } 141 | 142 | 143 | } 144 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/data/CustomArgumentControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.data; 2 | 3 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 4 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 5 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; 6 | 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | import org.springframework.samples.mvc.data.custom.CustomArgumentController; 10 | import org.springframework.samples.mvc.data.custom.CustomArgumentResolver; 11 | import org.springframework.test.web.servlet.MockMvc; 12 | 13 | public class CustomArgumentControllerTests { 14 | private MockMvc mockMvc; 15 | 16 | @Before 17 | public void setup() { 18 | this.mockMvc = standaloneSetup(new CustomArgumentController()) 19 | .setCustomArgumentResolvers(new CustomArgumentResolver()).build(); 20 | } 21 | 22 | @Test 23 | public void param() throws Exception { 24 | this.mockMvc.perform(get("/data/custom")) 25 | .andExpect(content().string("Got 'foo' request attribute value 'bar'")); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/data/DataControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.data; 2 | 3 | import static org.hamcrest.Matchers.startsWith; 4 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 5 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 6 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 7 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 8 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 9 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; 10 | 11 | import org.junit.Before; 12 | import org.junit.Test; 13 | import org.junit.runner.RunWith; 14 | import org.springframework.http.MediaType; 15 | import org.springframework.samples.mvc.AbstractContextControllerTests; 16 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 17 | import org.springframework.test.web.servlet.MockMvc; 18 | 19 | @RunWith(SpringJUnit4ClassRunner.class) 20 | public class DataControllerTests extends AbstractContextControllerTests { 21 | 22 | private MockMvc mockMvc; 23 | 24 | @Before 25 | public void setup() throws Exception { 26 | this.mockMvc = webAppContextSetup(this.wac).alwaysExpect(status().isOk()).build(); 27 | } 28 | 29 | @Test 30 | public void param() throws Exception { 31 | this.mockMvc.perform(get("/data/param?foo=bar")) 32 | .andExpect(content().string("Obtained 'foo' query parameter value 'bar'")); 33 | } 34 | 35 | @Test 36 | public void group() throws Exception { 37 | this.mockMvc.perform(get("/data/group?param1=foo¶m2=bar¶m3=baz")) 38 | .andExpect(content().string(startsWith( 39 | "Obtained parameter group org.springframework.samples.mvc.data.JavaBean@"))); 40 | } 41 | 42 | @Test 43 | public void pathVar() throws Exception { 44 | this.mockMvc.perform(get("/data/path/foo")) 45 | .andExpect(content().string("Obtained 'var' path variable value 'foo'")); 46 | } 47 | 48 | @Test 49 | public void matrixVar() throws Exception { 50 | this.mockMvc.perform(get("/data/matrixvars;foo=bar/simple")) 51 | .andExpect(content().string("Obtained matrix variable 'foo=bar' from path segment 'matrixvars'")); 52 | } 53 | 54 | @Test 55 | public void matrixVarMultiple() throws Exception { 56 | this.mockMvc.perform(get("/data/matrixvars;foo=bar1/multiple;foo=bar2")) 57 | .andExpect(content().string("Obtained matrix variable foo=bar1 from path segment 'matrixvars' and variable 'foo=bar2 from path segment 'multiple'")); 58 | } 59 | 60 | @Test 61 | public void header() throws Exception { 62 | this.mockMvc.perform(get("/data/header").accept(MediaType.ALL)) 63 | .andExpect(content().string("Obtained 'Accept' header '*/*'")); 64 | } 65 | 66 | @Test 67 | public void requestBody() throws Exception { 68 | this.mockMvc.perform( 69 | post("/data/body") 70 | .contentType(MediaType.TEXT_PLAIN) 71 | .content("foo".getBytes())) 72 | .andExpect(content().string("Posted request body 'foo'")); 73 | } 74 | 75 | @Test 76 | public void requestBodyAndHeaders() throws Exception { 77 | this.mockMvc.perform( 78 | post("/data/entity") 79 | .contentType(MediaType.TEXT_PLAIN) 80 | .content("foo".getBytes())) 81 | .andExpect(content().string( 82 | "Posted request body 'foo'; headers = {Content-Type=[text/plain], Content-Length=[3]}")); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/data/StandardArgumentsControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.data; 2 | 3 | import static org.hamcrest.Matchers.startsWith; 4 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 5 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 6 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 7 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 8 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; 9 | 10 | import org.junit.Before; 11 | import org.junit.Test; 12 | import org.springframework.http.MediaType; 13 | import org.springframework.samples.mvc.data.standard.StandardArgumentsController; 14 | import org.springframework.test.web.servlet.MockMvc; 15 | 16 | public class StandardArgumentsControllerTests { 17 | private MockMvc mockMvc; 18 | 19 | @Before 20 | public void setup() throws Exception { 21 | this.mockMvc = standaloneSetup(new StandardArgumentsController()).alwaysExpect(status().isOk()).build(); 22 | } 23 | 24 | @Test 25 | public void request() throws Exception { 26 | this.mockMvc.perform(get("/data/standard/request")) 27 | .andExpect(content().string(startsWith( 28 | "request = org.springframework.mock.web.MockHttpServletRequest@"))); 29 | } 30 | 31 | @Test 32 | public void requestReader() throws Exception { 33 | this.mockMvc.perform( 34 | post("/data/standard/request/reader") 35 | .contentType(MediaType.TEXT_PLAIN) 36 | .content("foo".getBytes())) 37 | .andExpect(content().string("Read char request body = foo")); 38 | } 39 | 40 | @Test 41 | public void requestIs() throws Exception { 42 | this.mockMvc.perform( 43 | post("/data/standard/request/is") 44 | .contentType(MediaType.TEXT_PLAIN) 45 | .content("foo".getBytes())) 46 | .andExpect(content().string("Read binary request body = foo")); 47 | } 48 | 49 | @Test 50 | public void response() throws Exception { 51 | this.mockMvc.perform(get("/data/standard/response")) 52 | .andExpect(content().string(startsWith( 53 | "response = org.springframework.mock.web.MockHttpServletResponse@"))); 54 | } 55 | 56 | @Test 57 | public void writer() throws Exception { 58 | this.mockMvc.perform(get("/data/standard/response/writer")) 59 | .andExpect(content().string("Wrote char response using Writer")); 60 | } 61 | 62 | @Test 63 | public void os() throws Exception { 64 | this.mockMvc.perform(get("/data/standard/response/os")) 65 | .andExpect(content().string("Wrote binary response using OutputStream")); 66 | } 67 | 68 | @Test 69 | public void session() throws Exception { 70 | this.mockMvc.perform(get("/data/standard/session")) 71 | .andExpect(content().string(startsWith( 72 | "session=org.springframework.mock.web.MockHttpSession@"))); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/exceptions/ExceptionControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.exceptions; 2 | 3 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 4 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 5 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 6 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; 7 | 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.springframework.samples.mvc.AbstractContextControllerTests; 12 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 13 | import org.springframework.test.web.servlet.MockMvc; 14 | 15 | @RunWith(SpringJUnit4ClassRunner.class) 16 | public class ExceptionControllerTests extends AbstractContextControllerTests { 17 | 18 | private MockMvc mockMvc; 19 | 20 | @Before 21 | public void setup() { 22 | this.mockMvc = webAppContextSetup(this.wac).build(); 23 | } 24 | 25 | @Test 26 | public void controllerExceptionHandler() throws Exception { 27 | this.mockMvc.perform(get("/exception")) 28 | .andExpect(status().isOk()) 29 | .andExpect(content().string("IllegalStateException handled!")); 30 | } 31 | 32 | @Test 33 | public void globalExceptionHandler() throws Exception { 34 | this.mockMvc.perform(get("/global-exception")) 35 | .andExpect(status().isOk()) 36 | .andExpect(content().string("Handled BusinessException")); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/fileupload/FileUploadControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.fileupload; 2 | 3 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.fileUpload; 4 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; 5 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.springframework.mock.web.MockMultipartFile; 10 | import org.springframework.samples.mvc.AbstractContextControllerTests; 11 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 12 | 13 | @RunWith(SpringJUnit4ClassRunner.class) 14 | public class FileUploadControllerTests extends AbstractContextControllerTests { 15 | 16 | @Test 17 | public void readString() throws Exception { 18 | 19 | MockMultipartFile file = new MockMultipartFile("file", "orig", null, "bar".getBytes()); 20 | 21 | webAppContextSetup(this.wac).build() 22 | .perform(fileUpload("/fileupload").file(file)) 23 | .andExpect(model().attribute("message", "File 'orig' uploaded successfully")); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/form/FormControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.form; 2 | 3 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 4 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 5 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.flash; 6 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; 7 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; 8 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 9 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; 10 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; 11 | 12 | import java.util.Calendar; 13 | import java.util.Date; 14 | import java.util.TimeZone; 15 | 16 | import org.junit.Before; 17 | import org.junit.Test; 18 | import org.springframework.http.MediaType; 19 | import org.springframework.test.web.servlet.MockMvc; 20 | import org.springframework.web.servlet.view.InternalResourceViewResolver; 21 | 22 | public class FormControllerTests { 23 | 24 | private MockMvc mockMvc; 25 | 26 | @Before 27 | public void setup() { 28 | 29 | InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); 30 | viewResolver.setPrefix("/WEB-INF/"); 31 | viewResolver.setSuffix(".jsp"); 32 | 33 | this.mockMvc = standaloneSetup(new FormController()).setViewResolvers(viewResolver).build(); 34 | } 35 | 36 | @Test 37 | public void submitSuccess() throws Exception { 38 | String timezone = getTimezone(1941, 12, 16); 39 | this.mockMvc.perform( 40 | post("/form") 41 | .param("name", "Joe") 42 | .param("age", "56") 43 | .param("birthDate", "1941-12-16") 44 | .param("phone", "(347) 888-1234") 45 | .param("currency", "$123.33") 46 | .param("percent", "89%") 47 | .param("inquiry", "comment") 48 | .param("inquiryDetails", "what is?") 49 | .param("additionalInfo[mvc]", "true") 50 | .param("_additionalInfo[mvc]", "on") 51 | .param("additionalInfo[java]", "true") 52 | .param("_additionalInfo[java]", "on") 53 | .param("subscribeNewsletter", "false")) 54 | .andExpect(status().isMovedTemporarily()) 55 | .andExpect(redirectedUrl("/form")) 56 | .andExpect(flash().attribute("message", 57 | "Form submitted successfully. Bound properties name='Joe', age=56, " + 58 | "birthDate=Tue Dec 16 00:00:00 " + timezone + " 1941, phone='(347) 888-1234', " + 59 | "currency=123.33, percent=0.89, inquiry=comment, inquiryDetails='what is?'," + 60 | " subscribeNewsletter=false, additionalInfo={java=true, mvc=true}")); 61 | } 62 | 63 | @Test 64 | public void submitSuccessAjax() throws Exception { 65 | String timezone = getTimezone(1941, 12, 16); 66 | this.mockMvc.perform( 67 | post("/form") 68 | .header("X-Requested-With", "XMLHttpRequest") 69 | .param("name", "Joe") 70 | .param("age", "56") 71 | .param("birthDate", "1941-12-16") 72 | .param("phone", "(347) 888-1234") 73 | .param("currency", "$123.33") 74 | .param("percent", "89%") 75 | .param("inquiry", "comment") 76 | .param("inquiryDetails", "what is?") 77 | .param("additionalInfo[mvc]", "true") 78 | .param("_additionalInfo[mvc]", "on") 79 | .param("additionalInfo[java]", "true") 80 | .param("_additionalInfo[java]", "on") 81 | .param("subscribeNewsletter", "false")) 82 | .andExpect(status().isOk()) 83 | .andExpect(view().name("form")) 84 | .andExpect(model().hasNoErrors()) 85 | .andExpect(model().attribute("message", 86 | "Form submitted successfully. Bound properties name='Joe', age=56, " + 87 | "birthDate=Tue Dec 16 00:00:00 " + timezone + " 1941, phone='(347) 888-1234', " + 88 | "currency=123.33, percent=0.89, inquiry=comment, inquiryDetails='what is?'," + 89 | " subscribeNewsletter=false, additionalInfo={java=true, mvc=true}")); 90 | } 91 | 92 | @Test 93 | public void submitError() throws Exception { 94 | this.mockMvc.perform( 95 | post("/form")) 96 | .andExpect(status().isOk()) 97 | .andExpect(view().name("form")) 98 | .andExpect(model().errorCount(2)) 99 | .andExpect(model().attributeHasFieldErrors("formBean", "name", "age")); 100 | } 101 | 102 | private String getTimezone(int year, int month, int day) 103 | { 104 | Calendar calendar = Calendar.getInstance(); 105 | calendar.set(Calendar.YEAR, year); 106 | calendar.set(Calendar.MONTH, month); 107 | calendar.set(Calendar.DAY_OF_MONTH, day); 108 | Date date = calendar.getTime(); 109 | TimeZone timezone = TimeZone.getDefault(); 110 | boolean inDaylight = timezone.inDaylightTime(date); 111 | return timezone.getDisplayName(inDaylight, TimeZone.SHORT); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/mapping/MappingControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.mapping; 2 | 3 | import static org.hamcrest.Matchers.startsWith; 4 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 5 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 6 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 7 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; 8 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 9 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.xpath; 10 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; 11 | 12 | import org.junit.Before; 13 | import org.junit.Test; 14 | import org.junit.runner.RunWith; 15 | import org.springframework.http.MediaType; 16 | import org.springframework.samples.mvc.AbstractContextControllerTests; 17 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 18 | import org.springframework.test.web.servlet.MockMvc; 19 | 20 | @RunWith(SpringJUnit4ClassRunner.class) 21 | public class MappingControllerTests extends AbstractContextControllerTests { 22 | 23 | private MockMvc mockMvc; 24 | 25 | @Before 26 | public void setup() { 27 | this.mockMvc = webAppContextSetup(this.wac).alwaysExpect(status().isOk()).build(); 28 | } 29 | 30 | @Test 31 | public void byPath() throws Exception { 32 | this.mockMvc.perform(get("/mapping/path")).andExpect(content().string("Mapped by path!")); 33 | } 34 | 35 | @Test 36 | public void byPathPattern() throws Exception { 37 | this.mockMvc.perform(get("/mapping/path/wildcard")) 38 | .andExpect(content().string("Mapped by path pattern ('/mapping/path/wildcard')")); 39 | } 40 | 41 | @Test 42 | public void byMethod() throws Exception { 43 | this.mockMvc.perform(get("/mapping/method")) 44 | .andExpect(content().string("Mapped by path + method")); 45 | } 46 | 47 | @Test 48 | public void byParameter() throws Exception { 49 | this.mockMvc.perform(get("/mapping/parameter?foo=bar")) 50 | .andExpect(content().string("Mapped by path + method + presence of query parameter!")); 51 | } 52 | 53 | @Test 54 | public void byNotParameter() throws Exception { 55 | this.mockMvc.perform(get("/mapping/parameter")) 56 | .andExpect(content().string("Mapped by path + method + not presence of query parameter!")); 57 | } 58 | 59 | @Test 60 | public void byHeader() throws Exception { 61 | this.mockMvc.perform(get("/mapping/header").header("FooHeader", "foo")) 62 | .andExpect(content().string("Mapped by path + method + presence of header!")); 63 | } 64 | 65 | @Test 66 | public void byHeaderNegation() throws Exception { 67 | this.mockMvc.perform(get("/mapping/header")) 68 | .andExpect(content().string("Mapped by path + method + absence of header!")); 69 | } 70 | 71 | @Test 72 | public void byConsumes() throws Exception { 73 | this.mockMvc.perform( 74 | post("/mapping/consumes") 75 | .contentType(MediaType.APPLICATION_JSON) 76 | .content("{ \"foo\": \"bar\", \"fruit\": \"apple\" }".getBytes())) 77 | .andExpect(content().string(startsWith("Mapped by path + method + consumable media type (javaBean"))); 78 | } 79 | 80 | @Test 81 | public void byProducesAcceptJson() throws Exception { 82 | this.mockMvc.perform(get("/mapping/produces").accept(MediaType.APPLICATION_JSON)) 83 | .andExpect(jsonPath("$.foo").value("bar")) 84 | .andExpect(jsonPath("$.fruit").value("apple")); 85 | } 86 | 87 | @Test 88 | public void byProducesAcceptXml() throws Exception { 89 | this.mockMvc.perform(get("/mapping/produces").accept(MediaType.APPLICATION_XML)) 90 | .andExpect(xpath("/javaBean/foo").string("bar")) 91 | .andExpect(xpath("/javaBean/fruit").string("apple")); 92 | } 93 | 94 | @Test 95 | public void byProducesJsonExtension() throws Exception { 96 | this.mockMvc.perform(get("/mapping/produces.json")) 97 | .andExpect(jsonPath("$.foo").value("bar")) 98 | .andExpect(jsonPath("$.fruit").value("apple")); 99 | } 100 | 101 | @Test 102 | public void byProducesXmlExtension() throws Exception { 103 | this.mockMvc.perform(get("/mapping/produces.xml")) 104 | .andExpect(xpath("/javaBean/foo").string("bar")) 105 | .andExpect(xpath("/javaBean/fruit").string("apple")); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/messageconverters/MessageConvertersControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.messageconverters; 2 | 3 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 4 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 5 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 6 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 7 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; 8 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 9 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; 10 | 11 | import org.junit.Before; 12 | import org.junit.Test; 13 | import org.junit.runner.RunWith; 14 | import org.springframework.http.MediaType; 15 | import org.springframework.samples.mvc.AbstractContextControllerTests; 16 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 17 | import org.springframework.test.web.servlet.MockMvc; 18 | 19 | @RunWith(SpringJUnit4ClassRunner.class) 20 | public class MessageConvertersControllerTests extends AbstractContextControllerTests { 21 | 22 | private static String URI = "/messageconverters/{action}"; 23 | 24 | private MockMvc mockMvc; 25 | 26 | @Before 27 | public void setup() { 28 | this.mockMvc = webAppContextSetup(this.wac).alwaysExpect(status().isOk()).build(); 29 | } 30 | 31 | @Test 32 | public void readString() throws Exception { 33 | this.mockMvc.perform(post(URI, "string").content("foo".getBytes())) 34 | .andExpect(content().string("Read string 'foo'")); 35 | } 36 | 37 | @Test 38 | public void writeString() throws Exception { 39 | this.mockMvc.perform(get(URI, "string")) 40 | .andExpect(content().string("Wrote a string")); 41 | } 42 | 43 | @Test 44 | public void readForm() throws Exception { 45 | this.mockMvc.perform( 46 | post(URI, "form") 47 | .contentType(MediaType.APPLICATION_FORM_URLENCODED) 48 | .param("foo", "bar") 49 | .param("fruit", "apple")) 50 | .andExpect(content().string("Read x-www-form-urlencoded: JavaBean {foo=[bar], fruit=[apple]}")); 51 | } 52 | 53 | @Test 54 | public void writeForm() throws Exception { 55 | this.mockMvc.perform(get(URI, "form")) 56 | .andExpect(content().contentType(MediaType.APPLICATION_FORM_URLENCODED)) 57 | .andExpect(content().string("foo=bar&fruit=apple")); 58 | } 59 | 60 | private static String XML = 61 | "" + 62 | "barapple"; 63 | 64 | @Test 65 | public void readXml() throws Exception { 66 | this.mockMvc.perform( 67 | post(URI, "xml") 68 | .contentType(MediaType.APPLICATION_XML) 69 | .content(XML.getBytes())) 70 | .andExpect(content().string("Read from XML: JavaBean {foo=[bar], fruit=[apple]}")); 71 | } 72 | 73 | @Test 74 | public void writeXml() throws Exception { 75 | this.mockMvc.perform(get(URI, "xml").accept(MediaType.APPLICATION_XML)) 76 | .andExpect(content().xml(XML)); 77 | } 78 | 79 | @Test 80 | public void readJson() throws Exception { 81 | this.mockMvc.perform( 82 | post(URI, "json") 83 | .contentType(MediaType.APPLICATION_JSON) 84 | .content("{ \"foo\": \"bar\", \"fruit\": \"apple\" }".getBytes())) 85 | .andExpect(content().string("Read from JSON: JavaBean {foo=[bar], fruit=[apple]}")); 86 | } 87 | 88 | @Test 89 | public void writeJson() throws Exception { 90 | this.mockMvc.perform(get(URI, "json").accept(MediaType.APPLICATION_JSON)) 91 | .andExpect(jsonPath("$.foo").value("bar")) 92 | .andExpect(jsonPath("$.fruit").value("apple")); 93 | } 94 | 95 | @Test 96 | public void writeJson2() throws Exception { 97 | this.mockMvc.perform(get(URI, "json").accept(MediaType.APPLICATION_JSON)) 98 | .andExpect(jsonPath("$.foo").value("bar")) 99 | .andExpect(jsonPath("$.fruit").value("apple")); 100 | } 101 | 102 | private static String ATOM_XML = "" + 103 | "My Atom feed"; 104 | 105 | @Test 106 | public void readAtom() throws Exception { 107 | this.mockMvc.perform( 108 | post(URI, "atom") 109 | .contentType(MediaType.APPLICATION_ATOM_XML) 110 | .content(ATOM_XML.getBytes())) 111 | .andExpect(content().string("Read My Atom feed")); 112 | } 113 | 114 | @Test 115 | public void writeAtom() throws Exception { 116 | this.mockMvc.perform(get(URI, "atom").accept(MediaType.APPLICATION_ATOM_XML)) 117 | .andExpect(content().xml(ATOM_XML)); 118 | } 119 | 120 | @Test 121 | public void readRss() throws Exception { 122 | 123 | String rss = " " + 124 | "My RSS feed"; 125 | 126 | this.mockMvc.perform( 127 | post(URI, "rss") 128 | .contentType(MediaType.valueOf("application/rss+xml")) 129 | .content(rss.getBytes())) 130 | .andExpect(content().string("Read My RSS feed")); 131 | } 132 | 133 | @Test 134 | public void writeRss() throws Exception { 135 | 136 | String rss = "" + 137 | "My RSS feedhttp://localhost:8080/mvc-showcase/rssDescription"; 138 | 139 | this.mockMvc.perform(get(URI, "rss").accept(MediaType.valueOf("application/rss+xml"))) 140 | .andExpect(content().xml(rss)); 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/redirect/RedirectControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.redirect; 2 | 3 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 4 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; 5 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 6 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; 7 | 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.springframework.format.support.DefaultFormattingConversionService; 11 | import org.springframework.test.web.servlet.MockMvc; 12 | 13 | public class RedirectControllerTests { 14 | 15 | private MockMvc mockMvc; 16 | 17 | @Before 18 | public void setup() throws Exception { 19 | this.mockMvc = standaloneSetup(new RedirectController(new DefaultFormattingConversionService())) 20 | .alwaysExpect(status().isFound()).build(); 21 | } 22 | 23 | @Test 24 | public void uriTemplate() throws Exception { 25 | this.mockMvc.perform(get("/redirect/uriTemplate")) 26 | .andExpect(redirectedUrl("/redirect/a123?date=12%2F31%2F11")); 27 | } 28 | 29 | @Test 30 | public void uriComponentsBuilder() throws Exception { 31 | this.mockMvc.perform(get("/redirect/uriComponentsBuilder")) 32 | .andExpect(redirectedUrl("/redirect/a123?date=12/31/11")); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/response/ResponseControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.response; 2 | 3 | import java.nio.charset.Charset; 4 | 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | 8 | import org.springframework.http.MediaType; 9 | import org.springframework.test.web.servlet.MockMvc; 10 | 11 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; 12 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; 13 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*; 14 | 15 | public class ResponseControllerTests { 16 | 17 | private MockMvc mockMvc; 18 | 19 | @Before 20 | public void setup() { 21 | this.mockMvc = standaloneSetup(new ResponseController()).build(); 22 | } 23 | 24 | @Test 25 | public void responseBody() throws Exception { 26 | this.mockMvc.perform(get("/response/annotation")) 27 | .andExpect(status().isOk()) 28 | .andExpect(content().string("The String ResponseBody")); 29 | } 30 | 31 | @Test 32 | public void responseCharsetAccept() throws Exception { 33 | this.mockMvc.perform( 34 | get("/response/charset/accept") 35 | .accept(new MediaType("text", "plain", Charset.forName("UTF-8")))) 36 | .andExpect(status().isOk()) 37 | .andExpect(content().string( 38 | "\u3053\u3093\u306b\u3061\u306f\u4e16\u754c\uff01 (\"Hello world!\" in Japanese)")); 39 | } 40 | 41 | @Test 42 | public void responseCharsetProduce() throws Exception { 43 | this.mockMvc.perform(get("/response/charset/produce")) 44 | .andExpect(status().isOk()) 45 | .andExpect(content().string( 46 | "\u3053\u3093\u306b\u3061\u306f\u4e16\u754c\uff01 (\"Hello world!\" in Japanese)")); 47 | } 48 | 49 | @Test 50 | public void responseEntityStatus() throws Exception { 51 | this.mockMvc.perform(get("/response/entity/status")) 52 | .andExpect(status().isForbidden()) 53 | .andExpect(content().string( 54 | "The String ResponseBody with custom status code (403 Forbidden)")); 55 | } 56 | 57 | @Test 58 | public void responseEntityHeaders() throws Exception { 59 | this.mockMvc.perform(get("/response/entity/headers")) 60 | .andExpect(status().isOk()) 61 | .andExpect(content().string( 62 | "The String ResponseBody with custom header Content-Type=text/plain")); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/simple/SimpleControllerRevisitedTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.simple; 2 | 3 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 4 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 5 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 6 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; 7 | 8 | import org.junit.Test; 9 | import org.springframework.http.MediaType; 10 | 11 | public class SimpleControllerRevisitedTests { 12 | 13 | @Test 14 | public void simple() throws Exception { 15 | standaloneSetup(new SimpleControllerRevisited()).build() 16 | .perform(get("/simple/revisited").accept(MediaType.TEXT_PLAIN)) 17 | .andExpect(status().isOk()) 18 | .andExpect(content().contentType("text/plain;charset=ISO-8859-1")) 19 | .andExpect(content().string("Hello world revisited!")); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/simple/SimpleControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.simple; 2 | 3 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 4 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 5 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 6 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; 7 | 8 | import org.junit.Test; 9 | 10 | public class SimpleControllerTests { 11 | 12 | @Test 13 | public void simple() throws Exception { 14 | standaloneSetup(new SimpleController()).build() 15 | .perform(get("/simple")) 16 | .andExpect(status().isOk()) 17 | .andExpect(content().contentType("text/plain;charset=ISO-8859-1")) 18 | .andExpect(content().string("Hello world!")); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/validation/ValidationControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.validation; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | 6 | import org.springframework.test.web.servlet.MockMvc; 7 | 8 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; 9 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; 10 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*; 11 | 12 | public class ValidationControllerTests { 13 | 14 | private MockMvc mockMvc; 15 | 16 | @Before 17 | public void setup() { 18 | this.mockMvc = standaloneSetup(new ValidationController()).alwaysExpect(status().isOk()).build(); 19 | } 20 | 21 | @Test 22 | public void validateSuccess() throws Exception { 23 | this.mockMvc.perform(get("/validate?number=3&date=2029-07-04")) 24 | .andExpect(content().string("No errors")); 25 | } 26 | 27 | @Test 28 | public void validateErrors() throws Exception { 29 | this.mockMvc.perform(get("/validate?number=3&date=2010-07-01")) 30 | .andExpect(content().string("Object has validation errors")); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/mvc/views/ViewsControllerTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.samples.mvc.views; 2 | 3 | import static org.hamcrest.Matchers.containsString; 4 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 5 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; 6 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 7 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; 8 | import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; 9 | 10 | import org.junit.Before; 11 | import org.junit.Test; 12 | import org.junit.runner.RunWith; 13 | import org.springframework.samples.mvc.AbstractContextControllerTests; 14 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 15 | import org.springframework.test.web.servlet.MockMvc; 16 | 17 | @RunWith(SpringJUnit4ClassRunner.class) 18 | public class ViewsControllerTests extends AbstractContextControllerTests { 19 | 20 | private MockMvc mockMvc; 21 | 22 | @Before 23 | public void setup() { 24 | this.mockMvc = webAppContextSetup(this.wac).alwaysExpect(status().isOk()).build(); 25 | } 26 | 27 | @Test 28 | public void htmlView() throws Exception { 29 | this.mockMvc.perform(get("/views/html")) 30 | .andExpect(view().name(containsString("views/html"))) 31 | .andExpect(model().attribute("foo", "bar")) 32 | .andExpect(model().attribute("fruit", "apple")) 33 | .andExpect(model().size(2)); 34 | } 35 | 36 | @Test 37 | public void viewName() throws Exception { 38 | this.mockMvc.perform(get("/views/viewName")) 39 | .andExpect(view().name(containsString("views/viewName"))) 40 | .andExpect(model().attribute("foo", "bar")) 41 | .andExpect(model().attribute("fruit", "apple")) 42 | .andExpect(model().size(2)); 43 | } 44 | 45 | @Test 46 | public void uriTemplate() throws Exception { 47 | this.mockMvc.perform(get("/views/pathVariables/bar/apple")) 48 | .andExpect(view().name(containsString("views/html"))); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/resources/log4j2-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | --------------------------------------------------------------------------------