forked from spring-projects/spring-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathview.xml
More file actions
2649 lines (2146 loc) · 113 KB
/
view.xml
File metadata and controls
2649 lines (2146 loc) · 113 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="view">
<title>View technologies</title>
<section id="view-introduction">
<title>Introduction</title>
<para>One of the areas in which Spring excels is in the separation of view
technologies from the rest of the MVC framework. For example, deciding to
use Velocity or XSLT in place of an existing JSP is primarily a matter of
configuration. This chapter covers the major view technologies that work
with Spring and touches briefly on how to add new ones. This chapter
assumes you are already familiar with <xref linkend="mvc-viewresolver" />
which covers the basics of how views in general are coupled to the MVC
framework.</para>
</section>
<section id="view-jsp">
<title>JSP & JSTL</title>
<para>Spring provides a couple of out-of-the-box solutions for JSP and
JSTL views. Using JSP or JSTL is done using a normal view resolver defined
in the <interfacename>WebApplicationContext</interfacename>. Furthermore,
of course you need to write some JSPs that will actually render the
view.</para>
<note>
<para>
Setting up your application to use JSTL is a common source of error,
mainly caused by confusion over the different servlet spec., JSP and JSTL
version numbers, what they mean and how to declare the taglibs correctly.
The article
<ulink url="http://www.mularien.com/blog/2008/04/24/how-to-reference-and-use-jstl-in-your-web-application/">
How to Reference and Use JSTL in your Web Application</ulink> provides a
useful guide to the common pitfalls and how to avoid them. Note that as of
Spring 3.0, the minimum supported servlet version is 2.4 (JSP 2.0 and JSTL 1.1),
which reduces the scope for confusion somewhat.
</para>
</note>
<section id="view-jsp-resolver">
<title>View resolvers</title>
<para>Just as with any other view technology you're integrating with
Spring, for JSPs you'll need a view resolver that will resolve your
views. The most commonly used view resolvers when developing with JSPs
are the <classname>InternalResourceViewResolver</classname> and the
<classname>ResourceBundleViewResolver</classname>. Both are declared in
the <interfacename>WebApplicationContext</interfacename>:</para>
<programlisting language="xml"><lineannotation><!-- the <classname>ResourceBundleViewResolver</classname> --></lineannotation>
<bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basename" value="views"/>
</bean>
<lineannotation># And a sample properties file is uses (views.properties in WEB-INF/classes):</lineannotation>
welcome.(class)=org.springframework.web.servlet.view.JstlView
welcome.url=/WEB-INF/jsp/welcome.jsp
productList.(class)=org.springframework.web.servlet.view.JstlView
productList.url=/WEB-INF/jsp/productlist.jsp</programlisting>
<para>As you can see, the
<classname>ResourceBundleViewResolver</classname> needs a properties
file defining the view names mapped to 1) a class and 2) a URL. With a
<classname>ResourceBundleViewResolver</classname> you can mix different
types of views using only one resolver.</para>
<programlisting language="xml"><bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean></programlisting>
<para>The <classname>InternalResourceBundleViewResolver</classname> can
be configured for using JSPs as described above. As a best practice, we
strongly encourage placing your JSP files in a directory under the
<filename class="directory">'WEB-INF'</filename> directory, so there can
be no direct access by clients.</para>
</section>
<section id="view-jsp-jstl">
<title>'Plain-old' JSPs versus JSTL</title>
<para>When using the Java Standard Tag Library you must use a special
view class, the <classname>JstlView</classname>, as JSTL needs some
preparation before things such as the I18N features will work.</para>
</section>
<section id="view-jsp-tags">
<title>Additional tags facilitating development</title>
<para>Spring provides data binding of request parameters to command
objects as described in earlier chapters. To facilitate the development
of JSP pages in combination with those data binding features, Spring
provides a few tags that make things even easier. All Spring tags have
<emphasis>HTML escaping</emphasis> features to enable or disable
escaping of characters.</para>
<para>The tag library descriptor (TLD) is included in the <filename
class="libraryfile">spring-webmvc.jar</filename>.
Further information about the individual tags can be found in
the appendix entitled <xref linkend="spring.tld" />.</para>
</section>
<section id="view-jsp-formtaglib">
<title>Using Spring's form tag library</title>
<para>As of version 2.0, Spring provides a comprehensive set of data
binding-aware tags for handling form elements when using JSP and Spring
Web MVC. Each tag provides support for the set of attributes of its
corresponding HTML tag counterpart, making the tags familiar and
intuitive to use. The tag-generated HTML is HTML 4.01/XHTML 1.0
compliant.</para>
<para>Unlike other form/input tag libraries, Spring's form tag library
is integrated with Spring Web MVC, giving the tags access to the command
object and reference data your controller deals with. As you will see in
the following examples, the form tags make JSPs easier to develop, read
and maintain.</para>
<para>Let's go through the form tags and look at an example of how each
tag is used. We have included generated HTML snippets where certain tags
require further commentary.</para>
<section id="view-jsp-formtaglib-configuration">
<title>Configuration</title>
<para>The form tag library comes bundled in
<literal>spring-webmvc.jar</literal>.
The library descriptor is called
<literal>spring-form.tld</literal>.</para>
<para>To use the tags from this library, add the following directive
to the top of your JSP page:</para>
<programlisting language="xml"><%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %></programlisting>
<para>... where <literal>form</literal> is the tag name prefix you
want to use for the tags from this library.</para>
</section>
<section id="view-jsp-formtaglib-formtag">
<title>The <literal>form</literal> tag</title>
<para>This tag renders an HTML 'form' tag and exposes a binding path
to inner tags for binding. It puts the command object in the
<literal>PageContext</literal> so that the command object can be
accessed by inner tags. <emphasis>All the other tags in this library
are nested tags of the <literal>form</literal> tag</emphasis>.</para>
<para>Let's assume we have a domain object called
<classname>User</classname>. It is a JavaBean with properties such as
<literal>firstName</literal> and <literal>lastName</literal>. We will
use it as the form backing object of our form controller which returns
<literal>form.jsp</literal>. Below is an example of what
<literal>form.jsp</literal> would look like:</para>
<programlisting language="xml"><form:form>
<table>
<tr>
<td>First Name:</td>
<td><form:input path="firstName" /></td>
</tr>
<tr>
<td>Last Name:</td>
<td><form:input path="lastName" /></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Save Changes" />
</td>
</tr>
</table>
</form:form></programlisting>
<para>The <literal>firstName</literal> and <literal>lastName</literal>
values are retrieved from the command object placed in the
<interfacename>PageContext</interfacename> by the page controller.
Keep reading to see more complex examples of how inner tags are used
with the <literal>form</literal> tag.</para>
<para>The generated HTML looks like a standard form:</para>
<programlisting language="xml"><form method="POST">
<table>
<tr>
<td>First Name:</td>
<td><input name="firstName" type="text" value="Harry"/></td>
</tr>
<tr>
<td>Last Name:</td>
<td><input name="lastName" type="text" value="Potter"/></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Save Changes" />
</td>
</tr>
</table>
</form></programlisting>
<para>The preceding JSP assumes that the variable name of the form
backing object is <literal>'command'</literal>. If you have put the
form backing object into the model under another name (definitely a
best practice), then you can bind the form to the named variable like
so:</para>
<programlisting language="xml"><form:form commandName="user">
<table>
<tr>
<td>First Name:</td>
<td><form:input path="firstName" /></td>
</tr>
<tr>
<td>Last Name:</td>
<td><form:input path="lastName" /></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Save Changes" />
</td>
</tr>
</table>
</form:form></programlisting>
</section>
<section id="view-jsp-formtaglib-inputtag">
<title>The <literal>input</literal> tag</title>
<para>This tag renders an HTML 'input' tag using the bound value
and type='text' by default. For an example of this tag, see <xref
linkend="view-jsp-formtaglib-formtag" />. Starting with Spring 3.1
you can use other types such HTML5-specific types like 'email',
'tel', 'date', and others.</para>
</section>
<section id="view-jsp-formtaglib-checkboxtag">
<title>The <literal>checkbox</literal> tag</title>
<para>This tag renders an HTML 'input' tag with type
'checkbox'.</para>
<para>Let's assume our <classname>User</classname> has preferences
such as newsletter subscription and a list of hobbies. Below is an
example of the <classname>Preferences</classname> class:</para>
<programlisting language="java">public class Preferences {
private boolean receiveNewsletter;
private String[] interests;
private String favouriteWord;
public boolean isReceiveNewsletter() {
return receiveNewsletter;
}
public void setReceiveNewsletter(boolean receiveNewsletter) {
this.receiveNewsletter = receiveNewsletter;
}
public String[] getInterests() {
return interests;
}
public void setInterests(String[] interests) {
this.interests = interests;
}
public String getFavouriteWord() {
return favouriteWord;
}
public void setFavouriteWord(String favouriteWord) {
this.favouriteWord = favouriteWord;
}
}</programlisting>
<para>The <literal>form.jsp</literal> would look like:</para>
<programlisting language="xml"><form:form>
<table>
<tr>
<td>Subscribe to newsletter?:</td>
<lineannotation><%-- Approach 1: Property is of type <classname>java.lang.Boolean</classname> --%></lineannotation>
<td><form:checkbox path="preferences.receiveNewsletter"/></td>
</tr>
<tr>
<td>Interests:</td>
<td>
<lineannotation><%-- Approach 2: Property is of an array or of type <interfacename>java.util.Collection</interfacename> --%></lineannotation>
Quidditch: <form:checkbox path="preferences.interests" value="Quidditch"/>
Herbology: <form:checkbox path="preferences.interests" value="Herbology"/>
Defence Against the Dark Arts: <form:checkbox path="preferences.interests"
value="Defence Against the Dark Arts"/>
</td>
</tr>
<tr>
<td>Favourite Word:</td>
<td>
<lineannotation><%-- Approach 3: Property is of type <classname>java.lang.Object</classname> --%></lineannotation>
Magic: <form:checkbox path="preferences.favouriteWord" value="Magic"/>
</td>
</tr>
</table>
</form:form></programlisting>
<para>There are 3 approaches to the <literal>checkbox</literal> tag
which should meet all your checkbox needs.</para>
<itemizedlist>
<listitem>
<para>Approach One - When the bound value is of type
<literal>java.lang.Boolean</literal>, the
<literal>input(checkbox)</literal> is marked as 'checked' if the
bound value is <literal>true</literal>. The
<literal>value</literal> attribute corresponds to the resolved
value of the <literal>setValue(Object)</literal> value
property.</para>
</listitem>
<listitem>
<para>Approach Two - When the bound value is of type
<literal>array</literal> or
<interfacename>java.util.Collection</interfacename>, the
<literal>input(checkbox)</literal> is marked as 'checked' if the
configured <literal>setValue(Object)</literal> value is present in
the bound <interfacename>Collection</interfacename>.</para>
</listitem>
<listitem>
<para>Approach Three - For any other bound value type, the
<literal>input(checkbox)</literal> is marked as 'checked' if the
configured <literal>setValue(Object)</literal> is equal to the
bound value.</para>
</listitem>
</itemizedlist>
<para>Note that regardless of the approach, the same HTML structure is
generated. Below is an HTML snippet of some checkboxes:</para>
<programlisting language="xml"><tr>
<td>Interests:</td>
<td>
Quidditch: <input name="preferences.interests" type="checkbox" value="Quidditch"/>
<input type="hidden" value="1" name="_preferences.interests"/>
Herbology: <input name="preferences.interests" type="checkbox" value="Herbology"/>
<input type="hidden" value="1" name="_preferences.interests"/>
Defence Against the Dark Arts: <input name="preferences.interests" type="checkbox"
value="Defence Against the Dark Arts"/>
<input type="hidden" value="1" name="_preferences.interests"/>
</td>
</tr></programlisting>
<para>What you might not expect to see is the additional hidden field
after each checkbox. When a checkbox in an HTML page is
<emphasis>not</emphasis> checked, its value will not be sent to the
server as part of the HTTP request parameters once the form is
submitted, so we need a workaround for this quirk in HTML in order for
Spring form data binding to work. The <literal>checkbox</literal> tag
follows the existing Spring convention of including a hidden parameter
prefixed by an underscore ("_") for each checkbox. By doing this, you
are effectively telling Spring that <quote>
<emphasis>the checkbox was visible in the form and I want my object
to which the form data will be bound to reflect the state of the
checkbox no matter what</emphasis>
</quote>.</para>
</section>
<section id="view-jsp-formtaglib-checkboxestag">
<title>The <literal>checkboxes</literal> tag</title>
<para>This tag renders multiple HTML 'input' tags with type
'checkbox'.</para>
<para>Building on the example from the previous
<classname>checkbox</classname> tag section. Sometimes you prefer not
to have to list all the possible hobbies in your JSP page. You would
rather provide a list at runtime of the available options and pass
that in to the tag. That is the purpose of the
<classname>checkboxes</classname> tag. You pass in an
<classname>Array</classname>, a <classname>List</classname> or a
<classname>Map</classname> containing the available options in the
"items" property. Typically the bound property is a collection so it
can hold multiple values selected by the user. Below is an example of
the JSP using this tag:</para>
<programlisting language="xml"><form:form>
<table>
<tr>
<td>Interests:</td>
<td>
<lineannotation><%-- Property is of an array or of type <interfacename>java.util.Collection</interfacename> --%></lineannotation>
<form:checkboxes path="preferences.interests" items="${interestList}"/>
</td>
</tr>
</table>
</form:form></programlisting>
<para>This example assumes that the "interestList" is a
<classname>List</classname> available as a model attribute containing
strings of the values to be selected from. In the case where you use a
Map, the map entry key will be used as the value and the map entry's
value will be used as the label to be displayed. You can also use a
custom object where you can provide the property names for the value
using "itemValue" and the label using "itemLabel".</para>
</section>
<section id="view-jsp-formtaglib-radiobuttontag">
<title>The <literal>radiobutton</literal> tag</title>
<para>This tag renders an HTML 'input' tag with type 'radio'.</para>
<para>A typical usage pattern will involve multiple tag instances
bound to the same property but with different values.</para>
<programlisting language="xml"><tr>
<td>Sex:</td>
<td>Male: <form:radiobutton path="sex" value="M"/> <br/>
Female: <form:radiobutton path="sex" value="F"/> </td>
</tr></programlisting>
</section>
<section id="view-jsp-formtaglib-radiobuttonstag">
<title>The <literal>radiobuttons</literal> tag</title>
<para>This tag renders multiple HTML 'input' tags with type
'radio'.</para>
<para>Just like the <classname>checkboxes</classname> tag above, you
might want to pass in the available options as a runtime variable. For
this usage you would use the <classname>radiobuttons</classname> tag.
You pass in an <classname>Array</classname>, a
<classname>List</classname> or a <classname>Map</classname> containing
the available options in the "items" property. In the case where you
use a Map, the map entry key will be used as the value and the map
entry's value will be used as the label to be displayed. You can also
use a custom object where you can provide the property names for the
value using "itemValue" and the label using "itemLabel".</para>
<programlisting language="xml"><tr>
<td>Sex:</td>
<td><form:radiobuttons path="sex" items="${sexOptions}"/></td>
</tr></programlisting>
</section>
<section id="view-jsp-formtaglib-passwordtag">
<title>The <literal>password</literal> tag</title>
<para>This tag renders an HTML 'input' tag with type 'password' using
the bound value.</para>
<programlisting language="xml"><tr>
<td>Password:</td>
<td>
<form:password path="password" />
</td>
</tr></programlisting>
<para>Please note that by default, the password value is
<emphasis>not</emphasis> shown. If you do want the password value to
be shown, then set the value of the <literal>'showPassword'</literal>
attribute to true, like so.</para>
<programlisting language="xml"><tr>
<td>Password:</td>
<td>
<form:password path="password" value="^76525bvHGq" showPassword="true" />
</td>
</tr></programlisting>
</section>
<section id="view-jsp-formtaglib-selecttag">
<title>The <literal>select</literal> tag</title>
<para>This tag renders an HTML 'select' element. It supports data
binding to the selected option as well as the use of nested
<literal>option</literal> and <literal>options</literal> tags.</para>
<para>Let's assume a <classname>User</classname> has a list of
skills.</para>
<programlisting language="xml"><tr>
<td>Skills:</td>
<td><form:select path="skills" items="${skills}"/></td>
</tr></programlisting>
<para>If the <literal>User's</literal> skill were in Herbology, the
HTML source of the 'Skills' row would look like:</para>
<programlisting language="xml"><tr>
<td>Skills:</td>
<td><select name="skills" multiple="true">
<option value="Potions">Potions</option>
<option value="Herbology" selected="selected">Herbology</option>
<option value="Quidditch">Quidditch</option></select>
</td>
</tr></programlisting>
</section>
<section id="view-jsp-formtaglib-optiontag">
<title>The <literal>option</literal> tag</title>
<para>This tag renders an HTML 'option'. It sets 'selected' as
appropriate based on the bound value.</para>
<programlisting language="xml"><tr>
<td>House:</td>
<td>
<form:select path="house">
<form:option value="Gryffindor"/>
<form:option value="Hufflepuff"/>
<form:option value="Ravenclaw"/>
<form:option value="Slytherin"/>
</form:select>
</td>
</tr></programlisting>
<para>If the <literal>User's</literal> house was in Gryffindor, the
HTML source of the 'House' row would look like:</para>
<programlisting language="xml"><tr>
<td>House:</td>
<td>
<select name="house">
<option value="Gryffindor" selected="selected">Gryffindor</option>
<option value="Hufflepuff">Hufflepuff</option>
<option value="Ravenclaw">Ravenclaw</option>
<option value="Slytherin">Slytherin</option>
</select>
</td>
</tr></programlisting>
</section>
<section id="view-jsp-formtaglib-optionstag">
<title>The <literal>options</literal> tag</title>
<para>This tag renders a list of HTML 'option' tags. It sets the
'selected' attribute as appropriate based on the bound value.</para>
<programlisting language="xml"><tr>
<td>Country:</td>
<td>
<form:select path="country">
<form:option value="-" label="--Please Select"/>
<form:options items="${countryList}" itemValue="code" itemLabel="name"/>
</form:select>
</td>
</tr></programlisting>
<para>If the <classname>User</classname> lived in the UK, the HTML
source of the 'Country' row would look like:</para>
<programlisting language="xml"><tr>
<td>Country:</td>
<td>
<select name="country">
<option value="-">--Please Select</option>
<option value="AT">Austria</option>
<option value="UK" selected="selected">United Kingdom</option>
<option value="US">United States</option>
</select>
</td>
</tr></programlisting>
<para>As the example shows, the combined usage of an
<literal>option</literal> tag with the <literal>options</literal> tag
generates the same standard HTML, but allows you to explicitly specify
a value in the JSP that is for display only (where it belongs) such as
the default string in the example: "-- Please Select".</para>
<para>The <literal>items</literal> attribute is typically populated
with a collection or array of item objects.
<literal>itemValue</literal> and <literal>itemLabel</literal> simply
refer to bean properties of those item objects, if specified;
otherwise, the item objects themselves will be stringified.
Alternatively, you may specify a <literal>Map</literal> of items, in
which case the map keys are interpreted as option values and the map
values correspond to option labels. If <literal>itemValue</literal>
and/or <literal>itemLabel</literal> happen to be specified as well,
the item value property will apply to the map key and the item label
property will apply to the map value.</para>
</section>
<section id="view-jsp-formtaglib-textAreatag">
<title>The <literal>textarea</literal> tag</title>
<para>This tag renders an HTML 'textarea'.</para>
<programlisting language="xml"><tr>
<td>Notes:</td>
<td><form:textarea path="notes" rows="3" cols="20" /></td>
<td><form:errors path="notes" /></td>
</tr></programlisting>
</section>
<section id="view-jsp-formtaglib-hiddeninputtag">
<title>The <literal>hidden</literal> tag</title>
<para>This tag renders an HTML 'input' tag with type 'hidden' using
the bound value. To submit an unbound hidden value, use the HTML
<literal>input</literal> tag with type 'hidden'.</para>
<programlisting language="xml"><form:hidden path="house" />
</programlisting>
<para>If we choose to submit the 'house' value as a hidden one, the
HTML would look like:</para>
<programlisting language="xml"><input name="house" type="hidden" value="Gryffindor"/>
</programlisting>
</section>
<section id="view-jsp-formtaglib-errorstag">
<title>The <literal>errors</literal> tag</title>
<para>This tag renders field errors in an HTML 'span' tag. It provides
access to the errors created in your controller or those that were
created by any validators associated with your controller.</para>
<para>Let's assume we want to display all error messages for the
<literal>firstName</literal> and <literal>lastName</literal> fields
once we submit the form. We have a validator for instances of the
<classname>User</classname> class called
<classname>UserValidator</classname>.</para>
<programlisting language="java">public class UserValidator implements Validator {
public boolean supports(Class candidate) {
return User.class.isAssignableFrom(candidate);
}
public void validate(Object obj, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "required", "Field is required.");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "required", "Field is required.");
}
}</programlisting>
<para>The <literal>form.jsp</literal> would look like:</para>
<programlisting language="xml"><form:form>
<table>
<tr>
<td>First Name:</td>
<td><form:input path="firstName" /></td>
<lineannotation><%-- Show errors for firstName field --%></lineannotation>
<td><form:errors path="firstName" /></td>
</tr>
<tr>
<td>Last Name:</td>
<td><form:input path="lastName" /></td>
<lineannotation><%-- Show errors for lastName field --%></lineannotation>
<td><form:errors path="lastName" /></td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="Save Changes" />
</td>
</tr>
</table>
</form:form></programlisting>
<para>If we submit a form with empty values in the
<literal>firstName</literal> and <literal>lastName</literal> fields,
this is what the HTML would look like:</para>
<programlisting language="xml"><form method="POST">
<table>
<tr>
<td>First Name:</td>
<td><input name="firstName" type="text" value=""/></td>
<lineannotation><%-- Associated errors to firstName field displayed --%></lineannotation>
<td><span name="firstName.errors">Field is required.</span></td>
</tr>
<tr>
<td>Last Name:</td>
<td><input name="lastName" type="text" value=""/></td>
<lineannotation><%-- Associated errors to lastName field displayed --%></lineannotation>
<td><span name="lastName.errors">Field is required.</span></td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="Save Changes" />
</td>
</tr>
</table>
</form></programlisting>
<para>What if we want to display the entire list of errors for a given
page? The example below shows that the <literal>errors</literal> tag
also supports some basic wildcarding functionality.</para>
<itemizedlist>
<listitem>
<para><literal>path="*"</literal> - displays all errors</para>
</listitem>
<listitem>
<para><literal>path="lastName"</literal> - displays all errors
associated with the <literal>lastName</literal> field</para>
</listitem>
<listitem>
<para>if <literal>path</literal> is omitted - object errors only are displayed</para>
</listitem>
</itemizedlist>
<para>The example below will display a list of errors at the top of
the page, followed by field-specific errors next to the fields:</para>
<programlisting language="xml"><form:form>
<form:errors path="*" cssClass="errorBox" />
<table>
<tr>
<td>First Name:</td>
<td><form:input path="firstName" /></td>
<td><form:errors path="firstName" /></td>
</tr>
<tr>
<td>Last Name:</td>
<td><form:input path="lastName" /></td>
<td><form:errors path="lastName" /></td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="Save Changes" />
</td>
</tr>
</table>
</form:form></programlisting>
<para>The HTML would look like:</para>
<programlisting language="xml"><form method="POST">
<span name="*.errors" class="errorBox">Field is required.<br/>Field is required.</span>
<table>
<tr>
<td>First Name:</td>
<td><input name="firstName" type="text" value=""/></td>
<td><span name="firstName.errors">Field is required.</span></td>
</tr>
<tr>
<td>Last Name:</td>
<td><input name="lastName" type="text" value=""/></td>
<td><span name="lastName.errors">Field is required.</span></td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="Save Changes" />
</td>
</tr>
</form></programlisting>
</section>
<section id="rest-method-conversion">
<title>HTTP Method Conversion</title>
<para>A key principle of REST is the use of the Uniform Interface.
This means that all resources (URLs) can be manipulated using the same
four HTTP methods: GET, PUT, POST, and DELETE. For each method, the
HTTP specification defines the exact semantics. For instance, a GET
should always be a safe operation, meaning that is has no side
effects, and a PUT or DELETE should be idempotent, meaning that you
can repeat these operations over and over again, but the end result
should be the same. While HTTP defines these four methods, HTML only
supports two: GET and POST. Fortunately, there are two possible
workarounds: you can either use JavaScript to do your PUT or DELETE,
or simply do a POST with the 'real' method as an additional parameter
(modeled as a hidden input field in an HTML form). This latter trick
is what Spring's <classname>HiddenHttpMethodFilter</classname> does.
This filter is a plain Servlet Filter and therefore it can be used in
combination with any web framework (not just Spring MVC). Simply add
this filter to your web.xml, and a POST with a hidden _method
parameter will be converted into the corresponding HTTP method
request.</para>
<para>To support HTTP method conversion the Spring MVC form tag was
updated to support setting the HTTP method. For example, the following
snippet taken from the updated Petclinic sample</para>
<programlisting language="xml"><form:form method="delete">
<p class="submit"><input type="submit" value="Delete Pet"/></p>
</form:form></programlisting>
<para>This will actually perform an HTTP POST, with the 'real' DELETE
method hidden behind a request parameter, to be picked up by the
<classname>HiddenHttpMethodFilter</classname>, as defined in web.xml:</para>
<programlisting language="java"><filter>
<filter-name>httpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>httpMethodFilter</filter-name>
<servlet-name>petclinic</servlet-name>
</filter-mapping></programlisting><para>The corresponding @Controller method
is shown below:</para>
<programlisting language="java">@RequestMapping(method = RequestMethod.DELETE)
public String deletePet(@PathVariable int ownerId, @PathVariable int petId) {
this.clinic.deletePet(petId);
return "redirect:/owners/" + ownerId;
}</programlisting>
</section>
<section id="view-jsp-formtaglib-html5">
<title>HTML5 Tags</title>
<para>Starting with Spring 3, the Spring form tag library allows entering
dynamic attributes, which means you can enter any HTML5 specific attributes.
</para>
<para>In Spring 3.1, the form input tag supports entering a type attribute
other than 'text'. This is intended to allow rendering new HTML5 specific
input types such as 'email', 'date', 'range', and others. Note that
entering type='text' is not required since 'text' is the default type.
</para>
</section>
</section>
</section>
<section id="view-tiles">
<title>Tiles</title>
<para>It is possible to integrate Tiles - just as any other view
technology - in web applications using Spring. The following describes in
a broad way how to do this.</para>
<para><emphasis>NOTE:</emphasis> This section focuses on Spring's support
for Tiles 2 (the standalone version of Tiles, requiring Java 5+) in the
<literal>org.springframework.web.servlet.view.tiles2</literal> package.
Spring also continues to support Tiles 1.x (a.k.a. "Struts Tiles", as
shipped with Struts 1.1+; compatible with Java 1.4) in the original
<literal>org.springframework.web.servlet.view.tiles</literal>
package.</para>
<section id="view-tiles-dependencies">
<title>Dependencies</title>
<para>To be able to use Tiles you have to have a couple of additional
dependencies included in your project. The following is the list of
dependencies you need.</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal>Tiles version 2.1.2 or higher</literal></para>
</listitem>
<listitem>
<para><literal>Commons BeanUtils</literal></para>
</listitem>
<listitem>
<para><literal>Commons Digester</literal></para>
</listitem>
<listitem>
<para><literal>Commons Logging</literal></para>
</listitem>
</itemizedlist>
</section>
<section id="view-tiles-integrate">
<title>How to integrate Tiles</title>
<para>To be able to use Tiles, you have to configure it using files
containing definitions (for basic information on definitions and other
Tiles concepts, please have a look at <ulink
url="http://tiles.apache.org" />). In Spring this is done using the
<classname>TilesConfigurer</classname>. Have a look at the following
piece of example ApplicationContext configuration:</para>
<programlisting language="xml"><bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/defs/general.xml</value>
<value>/WEB-INF/defs/widgets.xml</value>
<value>/WEB-INF/defs/administrator.xml</value>
<value>/WEB-INF/defs/customer.xml</value>
<value>/WEB-INF/defs/templates.xml</value>
</list>
</property>
</bean></programlisting>
<para>As you can see, there are five files containing definitions, which
are all located in the <filename
class="directory">'WEB-INF/defs'</filename> directory. At initialization
of the <interfacename>WebApplicationContext</interfacename>, the files
will be loaded and the definitions factory will be initialized. After
that has been done, the Tiles includes in the definition files can be
used as views within your Spring web application. To be able to use the
views you have to have a <interfacename>ViewResolver</interfacename>
just as with any other view technology used with Spring. Below you can
find two possibilities, the <classname>UrlBasedViewResolver</classname>
and the <classname>ResourceBundleViewResolver</classname>.</para>
<section id="view-tiles-url">
<title>
<classname>UrlBasedViewResolver</classname>
</title>
<para>The <classname>UrlBasedViewResolver</classname> instantiates the
given <literal>viewClass</literal> for each view it has to
resolve.</para>
<programlisting language="xml"><bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
</bean></programlisting>
</section>
<section id="view-tiles-resource">
<title>
<classname>ResourceBundleViewResolver</classname>
</title>
<para>The <classname>ResourceBundleViewResolver</classname> has to be
provided with a property file containing viewnames and viewclasses the
resolver can use:</para>
<programlisting language="xml"><bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basename" value="views"/>
</bean></programlisting>
<programlisting language="java">...
welcomeView.(class)=org.springframework.web.servlet.view.tiles2.TilesView
welcomeView.url=welcome <lineannotation>(this is the name of a Tiles definition)</lineannotation>
vetsView.(class)=org.springframework.web.servlet.view.tiles2.TilesView
vetsView.url=vetsView <lineannotation>(again, this is the name of a Tiles definition)</lineannotation>
findOwnersForm.(class)=org.springframework.web.servlet.view.JstlView
findOwnersForm.url=/WEB-INF/jsp/findOwners.jsp
...</programlisting>
<para>As you can see, when using the
<classname>ResourceBundleViewResolver</classname>, you can easily mix
different view technologies.</para>
<para>Note that the <classname>TilesView</classname> class for Tiles 2
supports JSTL (the JSP Standard Tag Library) out of the box, whereas
there is a separate <classname>TilesJstlView</classname> subclass in the
Tiles 1.x support.</para>
</section>
<section id="view-tiles-preparer">
<title><classname>SimpleSpringPreparerFactory</classname> and
<classname>SpringBeanPreparerFactory</classname></title>
<para>As an advanced feature, Spring also supports two special Tiles 2
<interfacename>PreparerFactory</interfacename> implementations. Check
out the Tiles documentation for details on how to use
<interfacename>ViewPreparer</interfacename> references in your Tiles
definition files.</para>
<para>Specify <classname>SimpleSpringPreparerFactory</classname> to
autowire ViewPreparer instances based on specified preparer classes,
applying Spring's container callbacks as well as applying configured
Spring BeanPostProcessors. If Spring's context-wide annotation-config
has been activated, annotations in ViewPreparer classes will be
automatically detected and applied. Note that this expects preparer
<emphasis>classes</emphasis> in the Tiles definition files, just like
the default <classname>PreparerFactory</classname> does.</para>
<para>Specify <classname>SpringBeanPreparerFactory</classname> to
operate on specified preparer <emphasis>names</emphasis> instead of
classes, obtaining the corresponding Spring bean from the
DispatcherServlet's application context. The full bean creation
process will be in the control of the Spring application context in
this case, allowing for the use of explicit dependency injection
configuration, scoped beans etc. Note that you need to define one
Spring bean definition per preparer name (as used in your Tiles
definitions).</para>
<programlisting language="xml"><bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/defs/general.xml</value>
<value>/WEB-INF/defs/widgets.xml</value>
<value>/WEB-INF/defs/administrator.xml</value>
<value>/WEB-INF/defs/customer.xml</value>
<value>/WEB-INF/defs/templates.xml</value>
</list>
</property>
<lineannotation><!-- resolving preparer names as Spring bean definition names --></lineannotation>
<property name="preparerFactoryClass"
value="org.springframework.web.servlet.view.tiles2.SpringBeanPreparerFactory"/>